* config/alpha/alpha.c, config/alpha/alpha.md,
[official-gcc.git] / gcc / fortran / trans-openmp.c
blob49368661591ebb3f8f4a69a259f5e965418e6dac
1 /* OpenMP directive translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2005, 2006 Free Software Foundation, Inc.
3 Contributed by Jakub Jelinek <jakub@redhat.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
20 02110-1301, USA. */
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tree.h"
27 #include "tree-gimple.h"
28 #include "ggc.h"
29 #include "toplev.h"
30 #include "real.h"
31 #include "gfortran.h"
32 #include "trans.h"
33 #include "trans-stmt.h"
34 #include "trans-types.h"
35 #include "trans-array.h"
36 #include "trans-const.h"
37 #include "arith.h"
40 /* True if OpenMP should privatize what this DECL points to rather
41 than the DECL itself. */
43 bool
44 gfc_omp_privatize_by_reference (tree decl)
46 tree type = TREE_TYPE (decl);
48 if (TREE_CODE (type) == REFERENCE_TYPE)
49 return true;
51 if (TREE_CODE (type) == POINTER_TYPE)
53 /* POINTER/ALLOCATABLE have aggregate types, all user variables
54 that have POINTER_TYPE type are supposed to be privatized
55 by reference. */
56 if (!DECL_ARTIFICIAL (decl))
57 return true;
59 /* Some arrays are expanded as DECL_ARTIFICIAL pointers
60 by the frontend. */
61 if (DECL_LANG_SPECIFIC (decl)
62 && GFC_DECL_SAVED_DESCRIPTOR (decl))
63 return true;
66 return false;
69 /* True if OpenMP sharing attribute of DECL is predetermined. */
71 enum omp_clause_default_kind
72 gfc_omp_predetermined_sharing (tree decl)
74 if (DECL_ARTIFICIAL (decl) && ! GFC_DECL_RESULT (decl))
75 return OMP_CLAUSE_DEFAULT_SHARED;
77 /* Cray pointees shouldn't be listed in any clauses and should be
78 gimplified to dereference of the corresponding Cray pointer.
79 Make them all private, so that they are emitted in the debug
80 information. */
81 if (GFC_DECL_CRAY_POINTEE (decl))
82 return OMP_CLAUSE_DEFAULT_PRIVATE;
84 /* COMMON and EQUIVALENCE decls are shared. They
85 are only referenced through DECL_VALUE_EXPR of the variables
86 contained in them. If those are privatized, they will not be
87 gimplified to the COMMON or EQUIVALENCE decls. */
88 if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
89 return OMP_CLAUSE_DEFAULT_SHARED;
91 if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
92 return OMP_CLAUSE_DEFAULT_SHARED;
94 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
98 /* Return code to initialize DECL with its default constructor, or
99 NULL if there's nothing to do. */
101 tree
102 gfc_omp_clause_default_ctor (tree clause ATTRIBUTE_UNUSED, tree decl)
104 tree type = TREE_TYPE (decl);
105 stmtblock_t block;
107 if (! GFC_DESCRIPTOR_TYPE_P (type))
108 return NULL;
110 /* Allocatable arrays in PRIVATE clauses need to be set to
111 "not currently allocated" allocation status. */
112 gfc_init_block (&block);
114 gfc_conv_descriptor_data_set_tuples (&block, decl, null_pointer_node);
116 return gfc_finish_block (&block);
120 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
121 disregarded in OpenMP construct, because it is going to be
122 remapped during OpenMP lowering. SHARED is true if DECL
123 is going to be shared, false if it is going to be privatized. */
125 bool
126 gfc_omp_disregard_value_expr (tree decl, bool shared)
128 if (GFC_DECL_COMMON_OR_EQUIV (decl)
129 && DECL_HAS_VALUE_EXPR_P (decl))
131 tree value = DECL_VALUE_EXPR (decl);
133 if (TREE_CODE (value) == COMPONENT_REF
134 && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
135 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
137 /* If variable in COMMON or EQUIVALENCE is privatized, return
138 true, as just that variable is supposed to be privatized,
139 not the whole COMMON or whole EQUIVALENCE.
140 For shared variables in COMMON or EQUIVALENCE, let them be
141 gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
142 from the same COMMON or EQUIVALENCE just one sharing of the
143 whole COMMON or EQUIVALENCE is enough. */
144 return ! shared;
148 if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
149 return ! shared;
151 return false;
154 /* Return true if DECL that is shared iff SHARED is true should
155 be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
156 flag set. */
158 bool
159 gfc_omp_private_debug_clause (tree decl, bool shared)
161 if (GFC_DECL_CRAY_POINTEE (decl))
162 return true;
164 if (GFC_DECL_COMMON_OR_EQUIV (decl)
165 && DECL_HAS_VALUE_EXPR_P (decl))
167 tree value = DECL_VALUE_EXPR (decl);
169 if (TREE_CODE (value) == COMPONENT_REF
170 && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
171 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
172 return shared;
175 return false;
178 /* Register language specific type size variables as potentially OpenMP
179 firstprivate variables. */
181 void
182 gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
184 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
186 int r;
188 gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
189 for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
191 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
192 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
193 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
195 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
196 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
201 static inline tree
202 gfc_trans_add_clause (tree node, tree tail)
204 OMP_CLAUSE_CHAIN (node) = tail;
205 return node;
208 static tree
209 gfc_trans_omp_variable (gfc_symbol *sym)
211 tree t = gfc_get_symbol_decl (sym);
212 tree parent_decl;
213 int parent_flag;
214 bool return_value;
215 bool alternate_entry;
216 bool entry_master;
218 return_value = sym->attr.function && sym->result == sym;
219 alternate_entry = sym->attr.function && sym->attr.entry
220 && sym->result == sym;
221 entry_master = sym->attr.result
222 && sym->ns->proc_name->attr.entry_master
223 && !gfc_return_by_reference (sym->ns->proc_name);
224 parent_decl = DECL_CONTEXT (current_function_decl);
226 if ((t == parent_decl && return_value)
227 || (sym->ns && sym->ns->proc_name
228 && sym->ns->proc_name->backend_decl == parent_decl
229 && (alternate_entry || entry_master)))
230 parent_flag = 1;
231 else
232 parent_flag = 0;
234 /* Special case for assigning the return value of a function.
235 Self recursive functions must have an explicit return value. */
236 if (return_value && (t == current_function_decl || parent_flag))
237 t = gfc_get_fake_result_decl (sym, parent_flag);
239 /* Similarly for alternate entry points. */
240 else if (alternate_entry
241 && (sym->ns->proc_name->backend_decl == current_function_decl
242 || parent_flag))
244 gfc_entry_list *el = NULL;
246 for (el = sym->ns->entries; el; el = el->next)
247 if (sym == el->sym)
249 t = gfc_get_fake_result_decl (sym, parent_flag);
250 break;
254 else if (entry_master
255 && (sym->ns->proc_name->backend_decl == current_function_decl
256 || parent_flag))
257 t = gfc_get_fake_result_decl (sym, parent_flag);
259 return t;
262 static tree
263 gfc_trans_omp_variable_list (enum omp_clause_code code, gfc_namelist *namelist,
264 tree list)
266 for (; namelist != NULL; namelist = namelist->next)
267 if (namelist->sym->attr.referenced)
269 tree t = gfc_trans_omp_variable (namelist->sym);
270 if (t != error_mark_node)
272 tree node = build_omp_clause (code);
273 OMP_CLAUSE_DECL (node) = t;
274 list = gfc_trans_add_clause (node, list);
277 return list;
280 static void
281 gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
283 gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
284 gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
285 gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
286 gfc_expr *e1, *e2, *e3, *e4;
287 gfc_ref *ref;
288 tree decl, backend_decl, stmt;
289 locus old_loc = gfc_current_locus;
290 const char *iname;
291 try t;
293 decl = OMP_CLAUSE_DECL (c);
294 gfc_current_locus = where;
296 /* Create a fake symbol for init value. */
297 memset (&init_val_sym, 0, sizeof (init_val_sym));
298 init_val_sym.ns = sym->ns;
299 init_val_sym.name = sym->name;
300 init_val_sym.ts = sym->ts;
301 init_val_sym.attr.referenced = 1;
302 init_val_sym.declared_at = where;
303 init_val_sym.attr.flavor = FL_VARIABLE;
304 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
305 init_val_sym.backend_decl = backend_decl;
307 /* Create a fake symbol for the outer array reference. */
308 outer_sym = *sym;
309 outer_sym.as = gfc_copy_array_spec (sym->as);
310 outer_sym.attr.dummy = 0;
311 outer_sym.attr.result = 0;
312 outer_sym.attr.flavor = FL_VARIABLE;
313 outer_sym.backend_decl = create_tmp_var_raw (TREE_TYPE (decl), NULL);
315 /* Create fake symtrees for it. */
316 symtree1 = gfc_new_symtree (&root1, sym->name);
317 symtree1->n.sym = sym;
318 gcc_assert (symtree1 == root1);
320 symtree2 = gfc_new_symtree (&root2, sym->name);
321 symtree2->n.sym = &init_val_sym;
322 gcc_assert (symtree2 == root2);
324 symtree3 = gfc_new_symtree (&root3, sym->name);
325 symtree3->n.sym = &outer_sym;
326 gcc_assert (symtree3 == root3);
328 /* Create expressions. */
329 e1 = gfc_get_expr ();
330 e1->expr_type = EXPR_VARIABLE;
331 e1->where = where;
332 e1->symtree = symtree1;
333 e1->ts = sym->ts;
334 e1->ref = ref = gfc_get_ref ();
335 ref->u.ar.where = where;
336 ref->u.ar.as = sym->as;
337 ref->u.ar.type = AR_FULL;
338 ref->u.ar.dimen = 0;
339 t = gfc_resolve_expr (e1);
340 gcc_assert (t == SUCCESS);
342 e2 = gfc_get_expr ();
343 e2->expr_type = EXPR_VARIABLE;
344 e2->where = where;
345 e2->symtree = symtree2;
346 e2->ts = sym->ts;
347 t = gfc_resolve_expr (e2);
348 gcc_assert (t == SUCCESS);
350 e3 = gfc_copy_expr (e1);
351 e3->symtree = symtree3;
352 t = gfc_resolve_expr (e3);
353 gcc_assert (t == SUCCESS);
355 iname = NULL;
356 switch (OMP_CLAUSE_REDUCTION_CODE (c))
358 case PLUS_EXPR:
359 case MINUS_EXPR:
360 e4 = gfc_add (e3, e1);
361 break;
362 case MULT_EXPR:
363 e4 = gfc_multiply (e3, e1);
364 break;
365 case TRUTH_ANDIF_EXPR:
366 e4 = gfc_and (e3, e1);
367 break;
368 case TRUTH_ORIF_EXPR:
369 e4 = gfc_or (e3, e1);
370 break;
371 case EQ_EXPR:
372 e4 = gfc_eqv (e3, e1);
373 break;
374 case NE_EXPR:
375 e4 = gfc_neqv (e3, e1);
376 break;
377 case MIN_EXPR:
378 iname = "min";
379 break;
380 case MAX_EXPR:
381 iname = "max";
382 break;
383 case BIT_AND_EXPR:
384 iname = "iand";
385 break;
386 case BIT_IOR_EXPR:
387 iname = "ior";
388 break;
389 case BIT_XOR_EXPR:
390 iname = "ieor";
391 break;
392 default:
393 gcc_unreachable ();
395 if (iname != NULL)
397 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
398 intrinsic_sym.ns = sym->ns;
399 intrinsic_sym.name = iname;
400 intrinsic_sym.ts = sym->ts;
401 intrinsic_sym.attr.referenced = 1;
402 intrinsic_sym.attr.intrinsic = 1;
403 intrinsic_sym.attr.function = 1;
404 intrinsic_sym.result = &intrinsic_sym;
405 intrinsic_sym.declared_at = where;
407 symtree4 = gfc_new_symtree (&root4, iname);
408 symtree4->n.sym = &intrinsic_sym;
409 gcc_assert (symtree4 == root4);
411 e4 = gfc_get_expr ();
412 e4->expr_type = EXPR_FUNCTION;
413 e4->where = where;
414 e4->symtree = symtree4;
415 e4->value.function.isym = gfc_find_function (iname);
416 e4->value.function.actual = gfc_get_actual_arglist ();
417 e4->value.function.actual->expr = e3;
418 e4->value.function.actual->next = gfc_get_actual_arglist ();
419 e4->value.function.actual->next->expr = e1;
421 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
422 e1 = gfc_copy_expr (e1);
423 e3 = gfc_copy_expr (e3);
424 t = gfc_resolve_expr (e4);
425 gcc_assert (t == SUCCESS);
427 /* Create the init statement list. */
428 pushlevel (0);
429 stmt = gfc_trans_assignment (e1, e2, false);
430 if (TREE_CODE (stmt) != BIND_EXPR)
431 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
432 else
433 poplevel (0, 0, 0);
434 OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
436 /* Create the merge statement list. */
437 pushlevel (0);
438 stmt = gfc_trans_assignment (e3, e4, false);
439 if (TREE_CODE (stmt) != BIND_EXPR)
440 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
441 else
442 poplevel (0, 0, 0);
443 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
445 /* And stick the placeholder VAR_DECL into the clause as well. */
446 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_sym.backend_decl;
448 gfc_current_locus = old_loc;
450 gfc_free_expr (e1);
451 gfc_free_expr (e2);
452 gfc_free_expr (e3);
453 gfc_free_expr (e4);
454 gfc_free (symtree1);
455 gfc_free (symtree2);
456 gfc_free (symtree3);
457 if (symtree4)
458 gfc_free (symtree4);
459 gfc_free_array_spec (outer_sym.as);
462 static tree
463 gfc_trans_omp_reduction_list (gfc_namelist *namelist, tree list,
464 enum tree_code reduction_code, locus where)
466 for (; namelist != NULL; namelist = namelist->next)
467 if (namelist->sym->attr.referenced)
469 tree t = gfc_trans_omp_variable (namelist->sym);
470 if (t != error_mark_node)
472 tree node = build_omp_clause (OMP_CLAUSE_REDUCTION);
473 OMP_CLAUSE_DECL (node) = t;
474 OMP_CLAUSE_REDUCTION_CODE (node) = reduction_code;
475 if (namelist->sym->attr.dimension)
476 gfc_trans_omp_array_reduction (node, namelist->sym, where);
477 list = gfc_trans_add_clause (node, list);
480 return list;
483 static tree
484 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
485 locus where)
487 tree omp_clauses = NULL_TREE, chunk_size, c, old_clauses;
488 int list;
489 enum omp_clause_code clause_code;
490 gfc_se se;
492 if (clauses == NULL)
493 return NULL_TREE;
495 for (list = 0; list < OMP_LIST_NUM; list++)
497 gfc_namelist *n = clauses->lists[list];
499 if (n == NULL)
500 continue;
501 if (list >= OMP_LIST_REDUCTION_FIRST
502 && list <= OMP_LIST_REDUCTION_LAST)
504 enum tree_code reduction_code;
505 switch (list)
507 case OMP_LIST_PLUS:
508 reduction_code = PLUS_EXPR;
509 break;
510 case OMP_LIST_MULT:
511 reduction_code = MULT_EXPR;
512 break;
513 case OMP_LIST_SUB:
514 reduction_code = MINUS_EXPR;
515 break;
516 case OMP_LIST_AND:
517 reduction_code = TRUTH_ANDIF_EXPR;
518 break;
519 case OMP_LIST_OR:
520 reduction_code = TRUTH_ORIF_EXPR;
521 break;
522 case OMP_LIST_EQV:
523 reduction_code = EQ_EXPR;
524 break;
525 case OMP_LIST_NEQV:
526 reduction_code = NE_EXPR;
527 break;
528 case OMP_LIST_MAX:
529 reduction_code = MAX_EXPR;
530 break;
531 case OMP_LIST_MIN:
532 reduction_code = MIN_EXPR;
533 break;
534 case OMP_LIST_IAND:
535 reduction_code = BIT_AND_EXPR;
536 break;
537 case OMP_LIST_IOR:
538 reduction_code = BIT_IOR_EXPR;
539 break;
540 case OMP_LIST_IEOR:
541 reduction_code = BIT_XOR_EXPR;
542 break;
543 default:
544 gcc_unreachable ();
546 old_clauses = omp_clauses;
547 omp_clauses
548 = gfc_trans_omp_reduction_list (n, omp_clauses, reduction_code,
549 where);
550 continue;
552 switch (list)
554 case OMP_LIST_PRIVATE:
555 clause_code = OMP_CLAUSE_PRIVATE;
556 goto add_clause;
557 case OMP_LIST_SHARED:
558 clause_code = OMP_CLAUSE_SHARED;
559 goto add_clause;
560 case OMP_LIST_FIRSTPRIVATE:
561 clause_code = OMP_CLAUSE_FIRSTPRIVATE;
562 goto add_clause;
563 case OMP_LIST_LASTPRIVATE:
564 clause_code = OMP_CLAUSE_LASTPRIVATE;
565 goto add_clause;
566 case OMP_LIST_COPYIN:
567 clause_code = OMP_CLAUSE_COPYIN;
568 goto add_clause;
569 case OMP_LIST_COPYPRIVATE:
570 clause_code = OMP_CLAUSE_COPYPRIVATE;
571 /* FALLTHROUGH */
572 add_clause:
573 omp_clauses
574 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses);
575 break;
576 default:
577 break;
581 if (clauses->if_expr)
583 tree if_var;
585 gfc_init_se (&se, NULL);
586 gfc_conv_expr (&se, clauses->if_expr);
587 gfc_add_block_to_block (block, &se.pre);
588 if_var = gfc_evaluate_now (se.expr, block);
589 gfc_add_block_to_block (block, &se.post);
591 c = build_omp_clause (OMP_CLAUSE_IF);
592 OMP_CLAUSE_IF_EXPR (c) = if_var;
593 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
596 if (clauses->num_threads)
598 tree num_threads;
600 gfc_init_se (&se, NULL);
601 gfc_conv_expr (&se, clauses->num_threads);
602 gfc_add_block_to_block (block, &se.pre);
603 num_threads = gfc_evaluate_now (se.expr, block);
604 gfc_add_block_to_block (block, &se.post);
606 c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
607 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
608 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
611 chunk_size = NULL_TREE;
612 if (clauses->chunk_size)
614 gfc_init_se (&se, NULL);
615 gfc_conv_expr (&se, clauses->chunk_size);
616 gfc_add_block_to_block (block, &se.pre);
617 chunk_size = gfc_evaluate_now (se.expr, block);
618 gfc_add_block_to_block (block, &se.post);
621 if (clauses->sched_kind != OMP_SCHED_NONE)
623 c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
624 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
625 switch (clauses->sched_kind)
627 case OMP_SCHED_STATIC:
628 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
629 break;
630 case OMP_SCHED_DYNAMIC:
631 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
632 break;
633 case OMP_SCHED_GUIDED:
634 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
635 break;
636 case OMP_SCHED_RUNTIME:
637 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
638 break;
639 default:
640 gcc_unreachable ();
642 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
645 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
647 c = build_omp_clause (OMP_CLAUSE_DEFAULT);
648 switch (clauses->default_sharing)
650 case OMP_DEFAULT_NONE:
651 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
652 break;
653 case OMP_DEFAULT_SHARED:
654 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
655 break;
656 case OMP_DEFAULT_PRIVATE:
657 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
658 break;
659 default:
660 gcc_unreachable ();
662 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
665 if (clauses->nowait)
667 c = build_omp_clause (OMP_CLAUSE_NOWAIT);
668 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
671 if (clauses->ordered)
673 c = build_omp_clause (OMP_CLAUSE_ORDERED);
674 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
677 return omp_clauses;
680 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
682 static tree
683 gfc_trans_omp_code (gfc_code *code, bool force_empty)
685 tree stmt;
687 pushlevel (0);
688 stmt = gfc_trans_code (code);
689 if (TREE_CODE (stmt) != BIND_EXPR)
691 if (!IS_EMPTY_STMT (stmt) || force_empty)
693 tree block = poplevel (1, 0, 0);
694 stmt = build3_v (BIND_EXPR, NULL, stmt, block);
696 else
697 poplevel (0, 0, 0);
699 else
700 poplevel (0, 0, 0);
701 return stmt;
705 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
706 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
708 static tree
709 gfc_trans_omp_atomic (gfc_code *code)
711 gfc_se lse;
712 gfc_se rse;
713 gfc_expr *expr2, *e;
714 gfc_symbol *var;
715 stmtblock_t block;
716 tree lhsaddr, type, rhs, x;
717 enum tree_code op = ERROR_MARK;
718 bool var_on_left = false;
720 code = code->block->next;
721 gcc_assert (code->op == EXEC_ASSIGN);
722 gcc_assert (code->next == NULL);
723 var = code->expr->symtree->n.sym;
725 gfc_init_se (&lse, NULL);
726 gfc_init_se (&rse, NULL);
727 gfc_start_block (&block);
729 gfc_conv_expr (&lse, code->expr);
730 gfc_add_block_to_block (&block, &lse.pre);
731 type = TREE_TYPE (lse.expr);
732 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
734 expr2 = code->expr2;
735 if (expr2->expr_type == EXPR_FUNCTION
736 && expr2->value.function.isym->generic_id == GFC_ISYM_CONVERSION)
737 expr2 = expr2->value.function.actual->expr;
739 if (expr2->expr_type == EXPR_OP)
741 gfc_expr *e;
742 switch (expr2->value.op.operator)
744 case INTRINSIC_PLUS:
745 op = PLUS_EXPR;
746 break;
747 case INTRINSIC_TIMES:
748 op = MULT_EXPR;
749 break;
750 case INTRINSIC_MINUS:
751 op = MINUS_EXPR;
752 break;
753 case INTRINSIC_DIVIDE:
754 if (expr2->ts.type == BT_INTEGER)
755 op = TRUNC_DIV_EXPR;
756 else
757 op = RDIV_EXPR;
758 break;
759 case INTRINSIC_AND:
760 op = TRUTH_ANDIF_EXPR;
761 break;
762 case INTRINSIC_OR:
763 op = TRUTH_ORIF_EXPR;
764 break;
765 case INTRINSIC_EQV:
766 op = EQ_EXPR;
767 break;
768 case INTRINSIC_NEQV:
769 op = NE_EXPR;
770 break;
771 default:
772 gcc_unreachable ();
774 e = expr2->value.op.op1;
775 if (e->expr_type == EXPR_FUNCTION
776 && e->value.function.isym->generic_id == GFC_ISYM_CONVERSION)
777 e = e->value.function.actual->expr;
778 if (e->expr_type == EXPR_VARIABLE
779 && e->symtree != NULL
780 && e->symtree->n.sym == var)
782 expr2 = expr2->value.op.op2;
783 var_on_left = true;
785 else
787 e = expr2->value.op.op2;
788 if (e->expr_type == EXPR_FUNCTION
789 && e->value.function.isym->generic_id == GFC_ISYM_CONVERSION)
790 e = e->value.function.actual->expr;
791 gcc_assert (e->expr_type == EXPR_VARIABLE
792 && e->symtree != NULL
793 && e->symtree->n.sym == var);
794 expr2 = expr2->value.op.op1;
795 var_on_left = false;
797 gfc_conv_expr (&rse, expr2);
798 gfc_add_block_to_block (&block, &rse.pre);
800 else
802 gcc_assert (expr2->expr_type == EXPR_FUNCTION);
803 switch (expr2->value.function.isym->generic_id)
805 case GFC_ISYM_MIN:
806 op = MIN_EXPR;
807 break;
808 case GFC_ISYM_MAX:
809 op = MAX_EXPR;
810 break;
811 case GFC_ISYM_IAND:
812 op = BIT_AND_EXPR;
813 break;
814 case GFC_ISYM_IOR:
815 op = BIT_IOR_EXPR;
816 break;
817 case GFC_ISYM_IEOR:
818 op = BIT_XOR_EXPR;
819 break;
820 default:
821 gcc_unreachable ();
823 e = expr2->value.function.actual->expr;
824 gcc_assert (e->expr_type == EXPR_VARIABLE
825 && e->symtree != NULL
826 && e->symtree->n.sym == var);
828 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
829 gfc_add_block_to_block (&block, &rse.pre);
830 if (expr2->value.function.actual->next->next != NULL)
832 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
833 gfc_actual_arglist *arg;
835 gfc_add_modify_stmt (&block, accum, rse.expr);
836 for (arg = expr2->value.function.actual->next->next; arg;
837 arg = arg->next)
839 gfc_init_block (&rse.pre);
840 gfc_conv_expr (&rse, arg->expr);
841 gfc_add_block_to_block (&block, &rse.pre);
842 x = fold_build2 (op, TREE_TYPE (accum), accum, rse.expr);
843 gfc_add_modify_stmt (&block, accum, x);
846 rse.expr = accum;
849 expr2 = expr2->value.function.actual->next->expr;
852 lhsaddr = save_expr (lhsaddr);
853 rhs = gfc_evaluate_now (rse.expr, &block);
854 x = convert (TREE_TYPE (rhs), build_fold_indirect_ref (lhsaddr));
856 if (var_on_left)
857 x = fold_build2 (op, TREE_TYPE (rhs), x, rhs);
858 else
859 x = fold_build2 (op, TREE_TYPE (rhs), rhs, x);
861 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
862 && TREE_CODE (type) != COMPLEX_TYPE)
863 x = build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (rhs)), x);
865 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
866 gfc_add_expr_to_block (&block, x);
868 gfc_add_block_to_block (&block, &lse.pre);
869 gfc_add_block_to_block (&block, &rse.pre);
871 return gfc_finish_block (&block);
874 static tree
875 gfc_trans_omp_barrier (void)
877 tree decl = built_in_decls [BUILT_IN_GOMP_BARRIER];
878 return build_call_expr (decl, 0);
881 static tree
882 gfc_trans_omp_critical (gfc_code *code)
884 tree name = NULL_TREE, stmt;
885 if (code->ext.omp_name != NULL)
886 name = get_identifier (code->ext.omp_name);
887 stmt = gfc_trans_code (code->block->next);
888 return build2_v (OMP_CRITICAL, stmt, name);
891 static tree
892 gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
893 gfc_omp_clauses *do_clauses)
895 gfc_se se;
896 tree dovar, stmt, from, to, step, type, init, cond, incr;
897 tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
898 stmtblock_t block;
899 stmtblock_t body;
900 int simple = 0;
901 bool dovar_found = false;
902 gfc_omp_clauses *clauses = code->ext.omp_clauses;
904 code = code->block->next;
905 gcc_assert (code->op == EXEC_DO);
907 if (pblock == NULL)
909 gfc_start_block (&block);
910 pblock = &block;
913 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
914 if (clauses)
916 gfc_namelist *n;
917 for (n = clauses->lists[OMP_LIST_LASTPRIVATE]; n != NULL; n = n->next)
918 if (code->ext.iterator->var->symtree->n.sym == n->sym)
919 break;
920 if (n == NULL)
921 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
922 if (code->ext.iterator->var->symtree->n.sym == n->sym)
923 break;
924 if (n != NULL)
925 dovar_found = true;
928 /* Evaluate all the expressions in the iterator. */
929 gfc_init_se (&se, NULL);
930 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
931 gfc_add_block_to_block (pblock, &se.pre);
932 dovar = se.expr;
933 type = TREE_TYPE (dovar);
934 gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
936 gfc_init_se (&se, NULL);
937 gfc_conv_expr_val (&se, code->ext.iterator->start);
938 gfc_add_block_to_block (pblock, &se.pre);
939 from = gfc_evaluate_now (se.expr, pblock);
941 gfc_init_se (&se, NULL);
942 gfc_conv_expr_val (&se, code->ext.iterator->end);
943 gfc_add_block_to_block (pblock, &se.pre);
944 to = gfc_evaluate_now (se.expr, pblock);
946 gfc_init_se (&se, NULL);
947 gfc_conv_expr_val (&se, code->ext.iterator->step);
948 gfc_add_block_to_block (pblock, &se.pre);
949 step = gfc_evaluate_now (se.expr, pblock);
951 /* Special case simple loops. */
952 if (integer_onep (step))
953 simple = 1;
954 else if (tree_int_cst_equal (step, integer_minus_one_node))
955 simple = -1;
957 /* Loop body. */
958 if (simple)
960 init = build2_v (GIMPLE_MODIFY_STMT, dovar, from);
961 cond = build2 (simple > 0 ? LE_EXPR : GE_EXPR, boolean_type_node,
962 dovar, to);
963 incr = fold_build2 (PLUS_EXPR, type, dovar, step);
964 incr = fold_build2 (GIMPLE_MODIFY_STMT, type, dovar, incr);
965 if (pblock != &block)
967 pushlevel (0);
968 gfc_start_block (&block);
970 gfc_start_block (&body);
972 else
974 /* STEP is not 1 or -1. Use:
975 for (count = 0; count < (to + step - from) / step; count++)
977 dovar = from + count * step;
978 body;
979 cycle_label:;
980 } */
981 tmp = fold_build2 (MINUS_EXPR, type, step, from);
982 tmp = fold_build2 (PLUS_EXPR, type, to, tmp);
983 tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
984 tmp = gfc_evaluate_now (tmp, pblock);
985 count = gfc_create_var (type, "count");
986 init = build2_v (GIMPLE_MODIFY_STMT, count, build_int_cst (type, 0));
987 cond = build2 (LT_EXPR, boolean_type_node, count, tmp);
988 incr = fold_build2 (PLUS_EXPR, type, count, build_int_cst (type, 1));
989 incr = fold_build2 (GIMPLE_MODIFY_STMT, type, count, incr);
991 if (pblock != &block)
993 pushlevel (0);
994 gfc_start_block (&block);
996 gfc_start_block (&body);
998 /* Initialize DOVAR. */
999 tmp = fold_build2 (MULT_EXPR, type, count, step);
1000 tmp = build2 (PLUS_EXPR, type, from, tmp);
1001 gfc_add_modify_stmt (&body, dovar, tmp);
1004 if (!dovar_found)
1006 tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
1007 OMP_CLAUSE_DECL (tmp) = dovar;
1008 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
1010 if (!simple)
1012 tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
1013 OMP_CLAUSE_DECL (tmp) = count;
1014 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
1017 /* Cycle statement is implemented with a goto. Exit statement must not be
1018 present for this loop. */
1019 cycle_label = gfc_build_label_decl (NULL_TREE);
1021 /* Put these labels where they can be found later. We put the
1022 labels in a TREE_LIST node (because TREE_CHAIN is already
1023 used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
1024 label in TREE_VALUE (backend_decl). */
1026 code->block->backend_decl = tree_cons (cycle_label, NULL, NULL);
1028 /* Main loop body. */
1029 tmp = gfc_trans_omp_code (code->block->next, true);
1030 gfc_add_expr_to_block (&body, tmp);
1032 /* Label for cycle statements (if needed). */
1033 if (TREE_USED (cycle_label))
1035 tmp = build1_v (LABEL_EXPR, cycle_label);
1036 gfc_add_expr_to_block (&body, tmp);
1039 /* End of loop body. */
1040 stmt = make_node (OMP_FOR);
1042 TREE_TYPE (stmt) = void_type_node;
1043 OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
1044 OMP_FOR_CLAUSES (stmt) = omp_clauses;
1045 OMP_FOR_INIT (stmt) = init;
1046 OMP_FOR_COND (stmt) = cond;
1047 OMP_FOR_INCR (stmt) = incr;
1048 gfc_add_expr_to_block (&block, stmt);
1050 return gfc_finish_block (&block);
1053 static tree
1054 gfc_trans_omp_flush (void)
1056 tree decl = built_in_decls [BUILT_IN_SYNCHRONIZE];
1057 return build_call_expr (decl, 0);
1060 static tree
1061 gfc_trans_omp_master (gfc_code *code)
1063 tree stmt = gfc_trans_code (code->block->next);
1064 if (IS_EMPTY_STMT (stmt))
1065 return stmt;
1066 return build1_v (OMP_MASTER, stmt);
1069 static tree
1070 gfc_trans_omp_ordered (gfc_code *code)
1072 return build1_v (OMP_ORDERED, gfc_trans_code (code->block->next));
1075 static tree
1076 gfc_trans_omp_parallel (gfc_code *code)
1078 stmtblock_t block;
1079 tree stmt, omp_clauses;
1081 gfc_start_block (&block);
1082 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1083 code->loc);
1084 stmt = gfc_trans_omp_code (code->block->next, true);
1085 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1086 gfc_add_expr_to_block (&block, stmt);
1087 return gfc_finish_block (&block);
1090 static tree
1091 gfc_trans_omp_parallel_do (gfc_code *code)
1093 stmtblock_t block, *pblock = NULL;
1094 gfc_omp_clauses parallel_clauses, do_clauses;
1095 tree stmt, omp_clauses = NULL_TREE;
1097 gfc_start_block (&block);
1099 memset (&do_clauses, 0, sizeof (do_clauses));
1100 if (code->ext.omp_clauses != NULL)
1102 memcpy (&parallel_clauses, code->ext.omp_clauses,
1103 sizeof (parallel_clauses));
1104 do_clauses.sched_kind = parallel_clauses.sched_kind;
1105 do_clauses.chunk_size = parallel_clauses.chunk_size;
1106 do_clauses.ordered = parallel_clauses.ordered;
1107 parallel_clauses.sched_kind = OMP_SCHED_NONE;
1108 parallel_clauses.chunk_size = NULL;
1109 parallel_clauses.ordered = false;
1110 omp_clauses = gfc_trans_omp_clauses (&block, &parallel_clauses,
1111 code->loc);
1113 do_clauses.nowait = true;
1114 if (!do_clauses.ordered && do_clauses.sched_kind != OMP_SCHED_STATIC)
1115 pblock = &block;
1116 else
1117 pushlevel (0);
1118 stmt = gfc_trans_omp_do (code, pblock, &do_clauses);
1119 if (TREE_CODE (stmt) != BIND_EXPR)
1120 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1121 else
1122 poplevel (0, 0, 0);
1123 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1124 OMP_PARALLEL_COMBINED (stmt) = 1;
1125 gfc_add_expr_to_block (&block, stmt);
1126 return gfc_finish_block (&block);
1129 static tree
1130 gfc_trans_omp_parallel_sections (gfc_code *code)
1132 stmtblock_t block;
1133 gfc_omp_clauses section_clauses;
1134 tree stmt, omp_clauses;
1136 memset (&section_clauses, 0, sizeof (section_clauses));
1137 section_clauses.nowait = true;
1139 gfc_start_block (&block);
1140 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1141 code->loc);
1142 pushlevel (0);
1143 stmt = gfc_trans_omp_sections (code, &section_clauses);
1144 if (TREE_CODE (stmt) != BIND_EXPR)
1145 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1146 else
1147 poplevel (0, 0, 0);
1148 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1149 OMP_PARALLEL_COMBINED (stmt) = 1;
1150 gfc_add_expr_to_block (&block, stmt);
1151 return gfc_finish_block (&block);
1154 static tree
1155 gfc_trans_omp_parallel_workshare (gfc_code *code)
1157 stmtblock_t block;
1158 gfc_omp_clauses workshare_clauses;
1159 tree stmt, omp_clauses;
1161 memset (&workshare_clauses, 0, sizeof (workshare_clauses));
1162 workshare_clauses.nowait = true;
1164 gfc_start_block (&block);
1165 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1166 code->loc);
1167 pushlevel (0);
1168 stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
1169 if (TREE_CODE (stmt) != BIND_EXPR)
1170 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1171 else
1172 poplevel (0, 0, 0);
1173 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1174 OMP_PARALLEL_COMBINED (stmt) = 1;
1175 gfc_add_expr_to_block (&block, stmt);
1176 return gfc_finish_block (&block);
1179 static tree
1180 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
1182 stmtblock_t block, body;
1183 tree omp_clauses, stmt;
1184 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
1186 gfc_start_block (&block);
1188 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
1190 gfc_init_block (&body);
1191 for (code = code->block; code; code = code->block)
1193 /* Last section is special because of lastprivate, so even if it
1194 is empty, chain it in. */
1195 stmt = gfc_trans_omp_code (code->next,
1196 has_lastprivate && code->block == NULL);
1197 if (! IS_EMPTY_STMT (stmt))
1199 stmt = build1_v (OMP_SECTION, stmt);
1200 gfc_add_expr_to_block (&body, stmt);
1203 stmt = gfc_finish_block (&body);
1205 stmt = build2_v (OMP_SECTIONS, stmt, omp_clauses);
1206 gfc_add_expr_to_block (&block, stmt);
1208 return gfc_finish_block (&block);
1211 static tree
1212 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
1214 tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
1215 tree stmt = gfc_trans_omp_code (code->block->next, true);
1216 stmt = build2_v (OMP_SINGLE, stmt, omp_clauses);
1217 return stmt;
1220 static tree
1221 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
1223 /* XXX */
1224 return gfc_trans_omp_single (code, clauses);
1227 tree
1228 gfc_trans_omp_directive (gfc_code *code)
1230 switch (code->op)
1232 case EXEC_OMP_ATOMIC:
1233 return gfc_trans_omp_atomic (code);
1234 case EXEC_OMP_BARRIER:
1235 return gfc_trans_omp_barrier ();
1236 case EXEC_OMP_CRITICAL:
1237 return gfc_trans_omp_critical (code);
1238 case EXEC_OMP_DO:
1239 return gfc_trans_omp_do (code, NULL, code->ext.omp_clauses);
1240 case EXEC_OMP_FLUSH:
1241 return gfc_trans_omp_flush ();
1242 case EXEC_OMP_MASTER:
1243 return gfc_trans_omp_master (code);
1244 case EXEC_OMP_ORDERED:
1245 return gfc_trans_omp_ordered (code);
1246 case EXEC_OMP_PARALLEL:
1247 return gfc_trans_omp_parallel (code);
1248 case EXEC_OMP_PARALLEL_DO:
1249 return gfc_trans_omp_parallel_do (code);
1250 case EXEC_OMP_PARALLEL_SECTIONS:
1251 return gfc_trans_omp_parallel_sections (code);
1252 case EXEC_OMP_PARALLEL_WORKSHARE:
1253 return gfc_trans_omp_parallel_workshare (code);
1254 case EXEC_OMP_SECTIONS:
1255 return gfc_trans_omp_sections (code, code->ext.omp_clauses);
1256 case EXEC_OMP_SINGLE:
1257 return gfc_trans_omp_single (code, code->ext.omp_clauses);
1258 case EXEC_OMP_WORKSHARE:
1259 return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
1260 default:
1261 gcc_unreachable ();