Revert emutls patch.
[official-gcc.git] / gcc / fortran / trans-openmp.c
blobe817196abb7dfb68d8fe11a2675340ae976b692e
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 (&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 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
304 init_val_sym.backend_decl = backend_decl;
306 /* Create a fake symbol for the outer array reference. */
307 outer_sym = *sym;
308 outer_sym.as = gfc_copy_array_spec (sym->as);
309 outer_sym.attr.dummy = 0;
310 outer_sym.attr.result = 0;
311 outer_sym.backend_decl = create_tmp_var_raw (TREE_TYPE (decl), NULL);
313 /* Create fake symtrees for it. */
314 symtree1 = gfc_new_symtree (&root1, sym->name);
315 symtree1->n.sym = sym;
316 gcc_assert (symtree1 == root1);
318 symtree2 = gfc_new_symtree (&root2, sym->name);
319 symtree2->n.sym = &init_val_sym;
320 gcc_assert (symtree2 == root2);
322 symtree3 = gfc_new_symtree (&root3, sym->name);
323 symtree3->n.sym = &outer_sym;
324 gcc_assert (symtree3 == root3);
326 /* Create expressions. */
327 e1 = gfc_get_expr ();
328 e1->expr_type = EXPR_VARIABLE;
329 e1->where = where;
330 e1->symtree = symtree1;
331 e1->ts = sym->ts;
332 e1->ref = ref = gfc_get_ref ();
333 ref->u.ar.where = where;
334 ref->u.ar.as = sym->as;
335 ref->u.ar.type = AR_FULL;
336 ref->u.ar.dimen = 0;
337 t = gfc_resolve_expr (e1);
338 gcc_assert (t == SUCCESS);
340 e2 = gfc_get_expr ();
341 e2->expr_type = EXPR_VARIABLE;
342 e2->where = where;
343 e2->symtree = symtree2;
344 e2->ts = sym->ts;
345 t = gfc_resolve_expr (e2);
346 gcc_assert (t == SUCCESS);
348 e3 = gfc_copy_expr (e1);
349 e3->symtree = symtree3;
350 t = gfc_resolve_expr (e3);
351 gcc_assert (t == SUCCESS);
353 iname = NULL;
354 switch (OMP_CLAUSE_REDUCTION_CODE (c))
356 case PLUS_EXPR:
357 case MINUS_EXPR:
358 e4 = gfc_add (e3, e1);
359 break;
360 case MULT_EXPR:
361 e4 = gfc_multiply (e3, e1);
362 break;
363 case TRUTH_ANDIF_EXPR:
364 e4 = gfc_and (e3, e1);
365 break;
366 case TRUTH_ORIF_EXPR:
367 e4 = gfc_or (e3, e1);
368 break;
369 case EQ_EXPR:
370 e4 = gfc_eqv (e3, e1);
371 break;
372 case NE_EXPR:
373 e4 = gfc_neqv (e3, e1);
374 break;
375 case MIN_EXPR:
376 iname = "min";
377 break;
378 case MAX_EXPR:
379 iname = "max";
380 break;
381 case BIT_AND_EXPR:
382 iname = "iand";
383 break;
384 case BIT_IOR_EXPR:
385 iname = "ior";
386 break;
387 case BIT_XOR_EXPR:
388 iname = "ieor";
389 break;
390 default:
391 gcc_unreachable ();
393 if (iname != NULL)
395 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
396 intrinsic_sym.ns = sym->ns;
397 intrinsic_sym.name = iname;
398 intrinsic_sym.ts = sym->ts;
399 intrinsic_sym.attr.referenced = 1;
400 intrinsic_sym.attr.intrinsic = 1;
401 intrinsic_sym.attr.function = 1;
402 intrinsic_sym.result = &intrinsic_sym;
403 intrinsic_sym.declared_at = where;
405 symtree4 = gfc_new_symtree (&root4, iname);
406 symtree4->n.sym = &intrinsic_sym;
407 gcc_assert (symtree4 == root4);
409 e4 = gfc_get_expr ();
410 e4->expr_type = EXPR_FUNCTION;
411 e4->where = where;
412 e4->symtree = symtree4;
413 e4->value.function.isym = gfc_find_function (iname);
414 e4->value.function.actual = gfc_get_actual_arglist ();
415 e4->value.function.actual->expr = e3;
416 e4->value.function.actual->next = gfc_get_actual_arglist ();
417 e4->value.function.actual->next->expr = e1;
419 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
420 e1 = gfc_copy_expr (e1);
421 e3 = gfc_copy_expr (e3);
422 t = gfc_resolve_expr (e4);
423 gcc_assert (t == SUCCESS);
425 /* Create the init statement list. */
426 pushlevel (0);
427 stmt = gfc_trans_assignment (e1, e2);
428 if (TREE_CODE (stmt) != BIND_EXPR)
429 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
430 else
431 poplevel (0, 0, 0);
432 OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
434 /* Create the merge statement list. */
435 pushlevel (0);
436 stmt = gfc_trans_assignment (e3, e4);
437 if (TREE_CODE (stmt) != BIND_EXPR)
438 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
439 else
440 poplevel (0, 0, 0);
441 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
443 /* And stick the placeholder VAR_DECL into the clause as well. */
444 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_sym.backend_decl;
446 gfc_current_locus = old_loc;
448 gfc_free_expr (e1);
449 gfc_free_expr (e2);
450 gfc_free_expr (e3);
451 gfc_free_expr (e4);
452 gfc_free (symtree1);
453 gfc_free (symtree2);
454 gfc_free (symtree3);
455 if (symtree4)
456 gfc_free (symtree4);
457 gfc_free_array_spec (outer_sym.as);
460 static tree
461 gfc_trans_omp_reduction_list (gfc_namelist *namelist, tree list,
462 enum tree_code reduction_code, locus where)
464 for (; namelist != NULL; namelist = namelist->next)
465 if (namelist->sym->attr.referenced)
467 tree t = gfc_trans_omp_variable (namelist->sym);
468 if (t != error_mark_node)
470 tree node = build_omp_clause (OMP_CLAUSE_REDUCTION);
471 OMP_CLAUSE_DECL (node) = t;
472 OMP_CLAUSE_REDUCTION_CODE (node) = reduction_code;
473 if (namelist->sym->attr.dimension)
474 gfc_trans_omp_array_reduction (node, namelist->sym, where);
475 list = gfc_trans_add_clause (node, list);
478 return list;
481 static tree
482 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
483 locus where)
485 tree omp_clauses = NULL_TREE, chunk_size, c, old_clauses;
486 int list;
487 enum omp_clause_code clause_code;
488 gfc_se se;
490 if (clauses == NULL)
491 return NULL_TREE;
493 for (list = 0; list < OMP_LIST_NUM; list++)
495 gfc_namelist *n = clauses->lists[list];
497 if (n == NULL)
498 continue;
499 if (list >= OMP_LIST_REDUCTION_FIRST
500 && list <= OMP_LIST_REDUCTION_LAST)
502 enum tree_code reduction_code;
503 switch (list)
505 case OMP_LIST_PLUS:
506 reduction_code = PLUS_EXPR;
507 break;
508 case OMP_LIST_MULT:
509 reduction_code = MULT_EXPR;
510 break;
511 case OMP_LIST_SUB:
512 reduction_code = MINUS_EXPR;
513 break;
514 case OMP_LIST_AND:
515 reduction_code = TRUTH_ANDIF_EXPR;
516 break;
517 case OMP_LIST_OR:
518 reduction_code = TRUTH_ORIF_EXPR;
519 break;
520 case OMP_LIST_EQV:
521 reduction_code = EQ_EXPR;
522 break;
523 case OMP_LIST_NEQV:
524 reduction_code = NE_EXPR;
525 break;
526 case OMP_LIST_MAX:
527 reduction_code = MAX_EXPR;
528 break;
529 case OMP_LIST_MIN:
530 reduction_code = MIN_EXPR;
531 break;
532 case OMP_LIST_IAND:
533 reduction_code = BIT_AND_EXPR;
534 break;
535 case OMP_LIST_IOR:
536 reduction_code = BIT_IOR_EXPR;
537 break;
538 case OMP_LIST_IEOR:
539 reduction_code = BIT_XOR_EXPR;
540 break;
541 default:
542 gcc_unreachable ();
544 old_clauses = omp_clauses;
545 omp_clauses
546 = gfc_trans_omp_reduction_list (n, omp_clauses, reduction_code,
547 where);
548 continue;
550 switch (list)
552 case OMP_LIST_PRIVATE:
553 clause_code = OMP_CLAUSE_PRIVATE;
554 goto add_clause;
555 case OMP_LIST_SHARED:
556 clause_code = OMP_CLAUSE_SHARED;
557 goto add_clause;
558 case OMP_LIST_FIRSTPRIVATE:
559 clause_code = OMP_CLAUSE_FIRSTPRIVATE;
560 goto add_clause;
561 case OMP_LIST_LASTPRIVATE:
562 clause_code = OMP_CLAUSE_LASTPRIVATE;
563 goto add_clause;
564 case OMP_LIST_COPYIN:
565 clause_code = OMP_CLAUSE_COPYIN;
566 goto add_clause;
567 case OMP_LIST_COPYPRIVATE:
568 clause_code = OMP_CLAUSE_COPYPRIVATE;
569 /* FALLTHROUGH */
570 add_clause:
571 omp_clauses
572 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses);
573 break;
574 default:
575 break;
579 if (clauses->if_expr)
581 tree if_var;
583 gfc_init_se (&se, NULL);
584 gfc_conv_expr (&se, clauses->if_expr);
585 gfc_add_block_to_block (block, &se.pre);
586 if_var = gfc_evaluate_now (se.expr, block);
587 gfc_add_block_to_block (block, &se.post);
589 c = build_omp_clause (OMP_CLAUSE_IF);
590 OMP_CLAUSE_IF_EXPR (c) = if_var;
591 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
594 if (clauses->num_threads)
596 tree num_threads;
598 gfc_init_se (&se, NULL);
599 gfc_conv_expr (&se, clauses->num_threads);
600 gfc_add_block_to_block (block, &se.pre);
601 num_threads = gfc_evaluate_now (se.expr, block);
602 gfc_add_block_to_block (block, &se.post);
604 c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
605 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
606 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
609 chunk_size = NULL_TREE;
610 if (clauses->chunk_size)
612 gfc_init_se (&se, NULL);
613 gfc_conv_expr (&se, clauses->chunk_size);
614 gfc_add_block_to_block (block, &se.pre);
615 chunk_size = gfc_evaluate_now (se.expr, block);
616 gfc_add_block_to_block (block, &se.post);
619 if (clauses->sched_kind != OMP_SCHED_NONE)
621 c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
622 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
623 switch (clauses->sched_kind)
625 case OMP_SCHED_STATIC:
626 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
627 break;
628 case OMP_SCHED_DYNAMIC:
629 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
630 break;
631 case OMP_SCHED_GUIDED:
632 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
633 break;
634 case OMP_SCHED_RUNTIME:
635 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
636 break;
637 default:
638 gcc_unreachable ();
640 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
643 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
645 c = build_omp_clause (OMP_CLAUSE_DEFAULT);
646 switch (clauses->default_sharing)
648 case OMP_DEFAULT_NONE:
649 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
650 break;
651 case OMP_DEFAULT_SHARED:
652 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
653 break;
654 case OMP_DEFAULT_PRIVATE:
655 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
656 break;
657 default:
658 gcc_unreachable ();
660 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
663 if (clauses->nowait)
665 c = build_omp_clause (OMP_CLAUSE_NOWAIT);
666 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
669 if (clauses->ordered)
671 c = build_omp_clause (OMP_CLAUSE_ORDERED);
672 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
675 return omp_clauses;
678 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
680 static tree
681 gfc_trans_omp_code (gfc_code *code, bool force_empty)
683 tree stmt;
685 pushlevel (0);
686 stmt = gfc_trans_code (code);
687 if (TREE_CODE (stmt) != BIND_EXPR)
689 if (!IS_EMPTY_STMT (stmt) || force_empty)
691 tree block = poplevel (1, 0, 0);
692 stmt = build3_v (BIND_EXPR, NULL, stmt, block);
694 else
695 poplevel (0, 0, 0);
697 else
698 poplevel (0, 0, 0);
699 return stmt;
703 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
704 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
706 static tree
707 gfc_trans_omp_atomic (gfc_code *code)
709 gfc_se lse;
710 gfc_se rse;
711 gfc_expr *expr2, *e;
712 gfc_symbol *var;
713 stmtblock_t block;
714 tree lhsaddr, type, rhs, x;
715 enum tree_code op = ERROR_MARK;
716 bool var_on_left = false;
718 code = code->block->next;
719 gcc_assert (code->op == EXEC_ASSIGN);
720 gcc_assert (code->next == NULL);
721 var = code->expr->symtree->n.sym;
723 gfc_init_se (&lse, NULL);
724 gfc_init_se (&rse, NULL);
725 gfc_start_block (&block);
727 gfc_conv_expr (&lse, code->expr);
728 gfc_add_block_to_block (&block, &lse.pre);
729 type = TREE_TYPE (lse.expr);
730 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
732 expr2 = code->expr2;
733 if (expr2->expr_type == EXPR_FUNCTION
734 && expr2->value.function.isym->generic_id == GFC_ISYM_CONVERSION)
735 expr2 = expr2->value.function.actual->expr;
737 if (expr2->expr_type == EXPR_OP)
739 gfc_expr *e;
740 switch (expr2->value.op.operator)
742 case INTRINSIC_PLUS:
743 op = PLUS_EXPR;
744 break;
745 case INTRINSIC_TIMES:
746 op = MULT_EXPR;
747 break;
748 case INTRINSIC_MINUS:
749 op = MINUS_EXPR;
750 break;
751 case INTRINSIC_DIVIDE:
752 if (expr2->ts.type == BT_INTEGER)
753 op = TRUNC_DIV_EXPR;
754 else
755 op = RDIV_EXPR;
756 break;
757 case INTRINSIC_AND:
758 op = TRUTH_ANDIF_EXPR;
759 break;
760 case INTRINSIC_OR:
761 op = TRUTH_ORIF_EXPR;
762 break;
763 case INTRINSIC_EQV:
764 op = EQ_EXPR;
765 break;
766 case INTRINSIC_NEQV:
767 op = NE_EXPR;
768 break;
769 default:
770 gcc_unreachable ();
772 e = expr2->value.op.op1;
773 if (e->expr_type == EXPR_FUNCTION
774 && e->value.function.isym->generic_id == GFC_ISYM_CONVERSION)
775 e = e->value.function.actual->expr;
776 if (e->expr_type == EXPR_VARIABLE
777 && e->symtree != NULL
778 && e->symtree->n.sym == var)
780 expr2 = expr2->value.op.op2;
781 var_on_left = true;
783 else
785 e = expr2->value.op.op2;
786 if (e->expr_type == EXPR_FUNCTION
787 && e->value.function.isym->generic_id == GFC_ISYM_CONVERSION)
788 e = e->value.function.actual->expr;
789 gcc_assert (e->expr_type == EXPR_VARIABLE
790 && e->symtree != NULL
791 && e->symtree->n.sym == var);
792 expr2 = expr2->value.op.op1;
793 var_on_left = false;
795 gfc_conv_expr (&rse, expr2);
796 gfc_add_block_to_block (&block, &rse.pre);
798 else
800 gcc_assert (expr2->expr_type == EXPR_FUNCTION);
801 switch (expr2->value.function.isym->generic_id)
803 case GFC_ISYM_MIN:
804 op = MIN_EXPR;
805 break;
806 case GFC_ISYM_MAX:
807 op = MAX_EXPR;
808 break;
809 case GFC_ISYM_IAND:
810 op = BIT_AND_EXPR;
811 break;
812 case GFC_ISYM_IOR:
813 op = BIT_IOR_EXPR;
814 break;
815 case GFC_ISYM_IEOR:
816 op = BIT_XOR_EXPR;
817 break;
818 default:
819 gcc_unreachable ();
821 e = expr2->value.function.actual->expr;
822 gcc_assert (e->expr_type == EXPR_VARIABLE
823 && e->symtree != NULL
824 && e->symtree->n.sym == var);
826 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
827 gfc_add_block_to_block (&block, &rse.pre);
828 if (expr2->value.function.actual->next->next != NULL)
830 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
831 gfc_actual_arglist *arg;
833 gfc_add_modify_expr (&block, accum, rse.expr);
834 for (arg = expr2->value.function.actual->next->next; arg;
835 arg = arg->next)
837 gfc_init_block (&rse.pre);
838 gfc_conv_expr (&rse, arg->expr);
839 gfc_add_block_to_block (&block, &rse.pre);
840 x = fold_build2 (op, TREE_TYPE (accum), accum, rse.expr);
841 gfc_add_modify_expr (&block, accum, x);
844 rse.expr = accum;
847 expr2 = expr2->value.function.actual->next->expr;
850 lhsaddr = save_expr (lhsaddr);
851 rhs = gfc_evaluate_now (rse.expr, &block);
852 x = convert (TREE_TYPE (rhs), build_fold_indirect_ref (lhsaddr));
854 if (var_on_left)
855 x = fold_build2 (op, TREE_TYPE (rhs), x, rhs);
856 else
857 x = fold_build2 (op, TREE_TYPE (rhs), rhs, x);
859 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
860 && TREE_CODE (type) != COMPLEX_TYPE)
861 x = build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (rhs)), x);
863 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
864 gfc_add_expr_to_block (&block, x);
866 gfc_add_block_to_block (&block, &lse.pre);
867 gfc_add_block_to_block (&block, &rse.pre);
869 return gfc_finish_block (&block);
872 static tree
873 gfc_trans_omp_barrier (void)
875 tree decl = built_in_decls [BUILT_IN_GOMP_BARRIER];
876 return build_function_call_expr (decl, NULL);
879 static tree
880 gfc_trans_omp_critical (gfc_code *code)
882 tree name = NULL_TREE, stmt;
883 if (code->ext.omp_name != NULL)
884 name = get_identifier (code->ext.omp_name);
885 stmt = gfc_trans_code (code->block->next);
886 return build2_v (OMP_CRITICAL, stmt, name);
889 static tree
890 gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
891 gfc_omp_clauses *do_clauses)
893 gfc_se se;
894 tree dovar, stmt, from, to, step, type, init, cond, incr;
895 tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
896 stmtblock_t block;
897 stmtblock_t body;
898 int simple = 0;
899 bool dovar_found = false;
900 gfc_omp_clauses *clauses = code->ext.omp_clauses;
902 code = code->block->next;
903 gcc_assert (code->op == EXEC_DO);
905 if (pblock == NULL)
907 gfc_start_block (&block);
908 pblock = &block;
911 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
912 if (clauses)
914 gfc_namelist *n;
915 for (n = clauses->lists[OMP_LIST_LASTPRIVATE]; n != NULL; n = n->next)
916 if (code->ext.iterator->var->symtree->n.sym == n->sym)
917 break;
918 if (n == NULL)
919 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
920 if (code->ext.iterator->var->symtree->n.sym == n->sym)
921 break;
922 if (n != NULL)
923 dovar_found = true;
926 /* Evaluate all the expressions in the iterator. */
927 gfc_init_se (&se, NULL);
928 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
929 gfc_add_block_to_block (pblock, &se.pre);
930 dovar = se.expr;
931 type = TREE_TYPE (dovar);
932 gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
934 gfc_init_se (&se, NULL);
935 gfc_conv_expr_val (&se, code->ext.iterator->start);
936 gfc_add_block_to_block (pblock, &se.pre);
937 from = gfc_evaluate_now (se.expr, pblock);
939 gfc_init_se (&se, NULL);
940 gfc_conv_expr_val (&se, code->ext.iterator->end);
941 gfc_add_block_to_block (pblock, &se.pre);
942 to = gfc_evaluate_now (se.expr, pblock);
944 gfc_init_se (&se, NULL);
945 gfc_conv_expr_val (&se, code->ext.iterator->step);
946 gfc_add_block_to_block (pblock, &se.pre);
947 step = gfc_evaluate_now (se.expr, pblock);
949 /* Special case simple loops. */
950 if (integer_onep (step))
951 simple = 1;
952 else if (tree_int_cst_equal (step, integer_minus_one_node))
953 simple = -1;
955 /* Loop body. */
956 if (simple)
958 init = build2_v (MODIFY_EXPR, dovar, from);
959 cond = build2 (simple > 0 ? LE_EXPR : GE_EXPR, boolean_type_node,
960 dovar, to);
961 incr = fold_build2 (PLUS_EXPR, type, dovar, step);
962 incr = fold_build2 (MODIFY_EXPR, type, dovar, incr);
963 if (pblock != &block)
965 pushlevel (0);
966 gfc_start_block (&block);
968 gfc_start_block (&body);
970 else
972 /* STEP is not 1 or -1. Use:
973 for (count = 0; count < (to + step - from) / step; count++)
975 dovar = from + count * step;
976 body;
977 cycle_label:;
978 } */
979 tmp = fold_build2 (MINUS_EXPR, type, step, from);
980 tmp = fold_build2 (PLUS_EXPR, type, to, tmp);
981 tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
982 tmp = gfc_evaluate_now (tmp, pblock);
983 count = gfc_create_var (type, "count");
984 init = build2_v (MODIFY_EXPR, count, build_int_cst (type, 0));
985 cond = build2 (LT_EXPR, boolean_type_node, count, tmp);
986 incr = fold_build2 (PLUS_EXPR, type, count, build_int_cst (type, 1));
987 incr = fold_build2 (MODIFY_EXPR, type, count, incr);
989 if (pblock != &block)
991 pushlevel (0);
992 gfc_start_block (&block);
994 gfc_start_block (&body);
996 /* Initialize DOVAR. */
997 tmp = fold_build2 (MULT_EXPR, type, count, step);
998 tmp = build2 (PLUS_EXPR, type, from, tmp);
999 gfc_add_modify_expr (&body, dovar, tmp);
1002 if (!dovar_found)
1004 tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
1005 OMP_CLAUSE_DECL (tmp) = dovar;
1006 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
1008 if (!simple)
1010 tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
1011 OMP_CLAUSE_DECL (tmp) = count;
1012 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
1015 /* Cycle statement is implemented with a goto. Exit statement must not be
1016 present for this loop. */
1017 cycle_label = gfc_build_label_decl (NULL_TREE);
1019 /* Put these labels where they can be found later. We put the
1020 labels in a TREE_LIST node (because TREE_CHAIN is already
1021 used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
1022 label in TREE_VALUE (backend_decl). */
1024 code->block->backend_decl = tree_cons (cycle_label, NULL, NULL);
1026 /* Main loop body. */
1027 tmp = gfc_trans_omp_code (code->block->next, true);
1028 gfc_add_expr_to_block (&body, tmp);
1030 /* Label for cycle statements (if needed). */
1031 if (TREE_USED (cycle_label))
1033 tmp = build1_v (LABEL_EXPR, cycle_label);
1034 gfc_add_expr_to_block (&body, tmp);
1037 /* End of loop body. */
1038 stmt = make_node (OMP_FOR);
1040 TREE_TYPE (stmt) = void_type_node;
1041 OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
1042 OMP_FOR_CLAUSES (stmt) = omp_clauses;
1043 OMP_FOR_INIT (stmt) = init;
1044 OMP_FOR_COND (stmt) = cond;
1045 OMP_FOR_INCR (stmt) = incr;
1046 gfc_add_expr_to_block (&block, stmt);
1048 return gfc_finish_block (&block);
1051 static tree
1052 gfc_trans_omp_flush (void)
1054 tree decl = built_in_decls [BUILT_IN_SYNCHRONIZE];
1055 return build_function_call_expr (decl, NULL);
1058 static tree
1059 gfc_trans_omp_master (gfc_code *code)
1061 tree stmt = gfc_trans_code (code->block->next);
1062 if (IS_EMPTY_STMT (stmt))
1063 return stmt;
1064 return build1_v (OMP_MASTER, stmt);
1067 static tree
1068 gfc_trans_omp_ordered (gfc_code *code)
1070 return build1_v (OMP_ORDERED, gfc_trans_code (code->block->next));
1073 static tree
1074 gfc_trans_omp_parallel (gfc_code *code)
1076 stmtblock_t block;
1077 tree stmt, omp_clauses;
1079 gfc_start_block (&block);
1080 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1081 code->loc);
1082 stmt = gfc_trans_omp_code (code->block->next, true);
1083 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1084 gfc_add_expr_to_block (&block, stmt);
1085 return gfc_finish_block (&block);
1088 static tree
1089 gfc_trans_omp_parallel_do (gfc_code *code)
1091 stmtblock_t block, *pblock = NULL;
1092 gfc_omp_clauses parallel_clauses, do_clauses;
1093 tree stmt, omp_clauses = NULL_TREE;
1095 gfc_start_block (&block);
1097 memset (&do_clauses, 0, sizeof (do_clauses));
1098 if (code->ext.omp_clauses != NULL)
1100 memcpy (&parallel_clauses, code->ext.omp_clauses,
1101 sizeof (parallel_clauses));
1102 do_clauses.sched_kind = parallel_clauses.sched_kind;
1103 do_clauses.chunk_size = parallel_clauses.chunk_size;
1104 do_clauses.ordered = parallel_clauses.ordered;
1105 parallel_clauses.sched_kind = OMP_SCHED_NONE;
1106 parallel_clauses.chunk_size = NULL;
1107 parallel_clauses.ordered = false;
1108 omp_clauses = gfc_trans_omp_clauses (&block, &parallel_clauses,
1109 code->loc);
1111 do_clauses.nowait = true;
1112 if (!do_clauses.ordered && do_clauses.sched_kind != OMP_SCHED_STATIC)
1113 pblock = &block;
1114 else
1115 pushlevel (0);
1116 stmt = gfc_trans_omp_do (code, pblock, &do_clauses);
1117 if (TREE_CODE (stmt) != BIND_EXPR)
1118 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1119 else
1120 poplevel (0, 0, 0);
1121 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1122 OMP_PARALLEL_COMBINED (stmt) = 1;
1123 gfc_add_expr_to_block (&block, stmt);
1124 return gfc_finish_block (&block);
1127 static tree
1128 gfc_trans_omp_parallel_sections (gfc_code *code)
1130 stmtblock_t block;
1131 gfc_omp_clauses section_clauses;
1132 tree stmt, omp_clauses;
1134 memset (&section_clauses, 0, sizeof (section_clauses));
1135 section_clauses.nowait = true;
1137 gfc_start_block (&block);
1138 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1139 code->loc);
1140 pushlevel (0);
1141 stmt = gfc_trans_omp_sections (code, &section_clauses);
1142 if (TREE_CODE (stmt) != BIND_EXPR)
1143 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1144 else
1145 poplevel (0, 0, 0);
1146 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1147 OMP_PARALLEL_COMBINED (stmt) = 1;
1148 gfc_add_expr_to_block (&block, stmt);
1149 return gfc_finish_block (&block);
1152 static tree
1153 gfc_trans_omp_parallel_workshare (gfc_code *code)
1155 stmtblock_t block;
1156 gfc_omp_clauses workshare_clauses;
1157 tree stmt, omp_clauses;
1159 memset (&workshare_clauses, 0, sizeof (workshare_clauses));
1160 workshare_clauses.nowait = true;
1162 gfc_start_block (&block);
1163 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1164 code->loc);
1165 pushlevel (0);
1166 stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
1167 if (TREE_CODE (stmt) != BIND_EXPR)
1168 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1169 else
1170 poplevel (0, 0, 0);
1171 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1172 OMP_PARALLEL_COMBINED (stmt) = 1;
1173 gfc_add_expr_to_block (&block, stmt);
1174 return gfc_finish_block (&block);
1177 static tree
1178 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
1180 stmtblock_t block, body;
1181 tree omp_clauses, stmt;
1182 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
1184 gfc_start_block (&block);
1186 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
1188 gfc_init_block (&body);
1189 for (code = code->block; code; code = code->block)
1191 /* Last section is special because of lastprivate, so even if it
1192 is empty, chain it in. */
1193 stmt = gfc_trans_omp_code (code->next,
1194 has_lastprivate && code->block == NULL);
1195 if (! IS_EMPTY_STMT (stmt))
1197 stmt = build1_v (OMP_SECTION, stmt);
1198 gfc_add_expr_to_block (&body, stmt);
1201 stmt = gfc_finish_block (&body);
1203 stmt = build2_v (OMP_SECTIONS, stmt, omp_clauses);
1204 gfc_add_expr_to_block (&block, stmt);
1206 return gfc_finish_block (&block);
1209 static tree
1210 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
1212 tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
1213 tree stmt = gfc_trans_omp_code (code->block->next, true);
1214 stmt = build2_v (OMP_SINGLE, stmt, omp_clauses);
1215 return stmt;
1218 static tree
1219 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
1221 /* XXX */
1222 return gfc_trans_omp_single (code, clauses);
1225 tree
1226 gfc_trans_omp_directive (gfc_code *code)
1228 switch (code->op)
1230 case EXEC_OMP_ATOMIC:
1231 return gfc_trans_omp_atomic (code);
1232 case EXEC_OMP_BARRIER:
1233 return gfc_trans_omp_barrier ();
1234 case EXEC_OMP_CRITICAL:
1235 return gfc_trans_omp_critical (code);
1236 case EXEC_OMP_DO:
1237 return gfc_trans_omp_do (code, NULL, code->ext.omp_clauses);
1238 case EXEC_OMP_FLUSH:
1239 return gfc_trans_omp_flush ();
1240 case EXEC_OMP_MASTER:
1241 return gfc_trans_omp_master (code);
1242 case EXEC_OMP_ORDERED:
1243 return gfc_trans_omp_ordered (code);
1244 case EXEC_OMP_PARALLEL:
1245 return gfc_trans_omp_parallel (code);
1246 case EXEC_OMP_PARALLEL_DO:
1247 return gfc_trans_omp_parallel_do (code);
1248 case EXEC_OMP_PARALLEL_SECTIONS:
1249 return gfc_trans_omp_parallel_sections (code);
1250 case EXEC_OMP_PARALLEL_WORKSHARE:
1251 return gfc_trans_omp_parallel_workshare (code);
1252 case EXEC_OMP_SECTIONS:
1253 return gfc_trans_omp_sections (code, code->ext.omp_clauses);
1254 case EXEC_OMP_SINGLE:
1255 return gfc_trans_omp_single (code, code->ext.omp_clauses);
1256 case EXEC_OMP_WORKSHARE:
1257 return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
1258 default:
1259 gcc_unreachable ();