1 /* OpenMP directive translation -- generate GCC trees from gfc_code.
2 Copyright (C) 2005, 2006, 2007 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 3, or (at your option) any later
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
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
26 #include "tree-gimple.h"
32 #include "trans-stmt.h"
33 #include "trans-types.h"
34 #include "trans-array.h"
35 #include "trans-const.h"
39 /* True if OpenMP should privatize what this DECL points to rather
40 than the DECL itself. */
43 gfc_omp_privatize_by_reference (tree decl)
45 tree type = TREE_TYPE (decl);
47 if (TREE_CODE (type) == REFERENCE_TYPE)
50 if (TREE_CODE (type) == POINTER_TYPE)
52 /* Array POINTER/ALLOCATABLE have aggregate types, all user variables
53 that have POINTER_TYPE type and don't have GFC_POINTER_TYPE_P
54 set are supposed to be privatized by reference. */
55 if (GFC_POINTER_TYPE_P (type))
58 if (!DECL_ARTIFICIAL (decl))
61 /* Some arrays are expanded as DECL_ARTIFICIAL pointers
63 if (DECL_LANG_SPECIFIC (decl)
64 && GFC_DECL_SAVED_DESCRIPTOR (decl))
71 /* True if OpenMP sharing attribute of DECL is predetermined. */
73 enum omp_clause_default_kind
74 gfc_omp_predetermined_sharing (tree decl)
76 if (DECL_ARTIFICIAL (decl) && ! GFC_DECL_RESULT (decl))
77 return OMP_CLAUSE_DEFAULT_SHARED;
79 /* Cray pointees shouldn't be listed in any clauses and should be
80 gimplified to dereference of the corresponding Cray pointer.
81 Make them all private, so that they are emitted in the debug
83 if (GFC_DECL_CRAY_POINTEE (decl))
84 return OMP_CLAUSE_DEFAULT_PRIVATE;
86 /* COMMON and EQUIVALENCE decls are shared. They
87 are only referenced through DECL_VALUE_EXPR of the variables
88 contained in them. If those are privatized, they will not be
89 gimplified to the COMMON or EQUIVALENCE decls. */
90 if (GFC_DECL_COMMON_OR_EQUIV (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
91 return OMP_CLAUSE_DEFAULT_SHARED;
93 if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl))
94 return OMP_CLAUSE_DEFAULT_SHARED;
96 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
100 /* Return code to initialize DECL with its default constructor, or
101 NULL if there's nothing to do. */
104 gfc_omp_clause_default_ctor (tree clause ATTRIBUTE_UNUSED, tree decl)
106 tree type = TREE_TYPE (decl);
109 if (! GFC_DESCRIPTOR_TYPE_P (type))
112 /* Allocatable arrays in PRIVATE clauses need to be set to
113 "not currently allocated" allocation status. */
114 gfc_init_block (&block);
116 gfc_conv_descriptor_data_set_tuples (&block, decl, null_pointer_node);
118 return gfc_finish_block (&block);
122 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be
123 disregarded in OpenMP construct, because it is going to be
124 remapped during OpenMP lowering. SHARED is true if DECL
125 is going to be shared, false if it is going to be privatized. */
128 gfc_omp_disregard_value_expr (tree decl, bool shared)
130 if (GFC_DECL_COMMON_OR_EQUIV (decl)
131 && DECL_HAS_VALUE_EXPR_P (decl))
133 tree value = DECL_VALUE_EXPR (decl);
135 if (TREE_CODE (value) == COMPONENT_REF
136 && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
137 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
139 /* If variable in COMMON or EQUIVALENCE is privatized, return
140 true, as just that variable is supposed to be privatized,
141 not the whole COMMON or whole EQUIVALENCE.
142 For shared variables in COMMON or EQUIVALENCE, let them be
143 gimplified to DECL_VALUE_EXPR, so that for multiple shared vars
144 from the same COMMON or EQUIVALENCE just one sharing of the
145 whole COMMON or EQUIVALENCE is enough. */
150 if (GFC_DECL_RESULT (decl) && DECL_HAS_VALUE_EXPR_P (decl))
156 /* Return true if DECL that is shared iff SHARED is true should
157 be put into OMP_CLAUSE_PRIVATE with OMP_CLAUSE_PRIVATE_DEBUG
161 gfc_omp_private_debug_clause (tree decl, bool shared)
163 if (GFC_DECL_CRAY_POINTEE (decl))
166 if (GFC_DECL_COMMON_OR_EQUIV (decl)
167 && DECL_HAS_VALUE_EXPR_P (decl))
169 tree value = DECL_VALUE_EXPR (decl);
171 if (TREE_CODE (value) == COMPONENT_REF
172 && TREE_CODE (TREE_OPERAND (value, 0)) == VAR_DECL
173 && GFC_DECL_COMMON_OR_EQUIV (TREE_OPERAND (value, 0)))
180 /* Register language specific type size variables as potentially OpenMP
181 firstprivate variables. */
184 gfc_omp_firstprivatize_type_sizes (struct gimplify_omp_ctx *ctx, tree type)
186 if (GFC_ARRAY_TYPE_P (type) || GFC_DESCRIPTOR_TYPE_P (type))
190 gcc_assert (TYPE_LANG_SPECIFIC (type) != NULL);
191 for (r = 0; r < GFC_TYPE_ARRAY_RANK (type); r++)
193 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_LBOUND (type, r));
194 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_UBOUND (type, r));
195 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_STRIDE (type, r));
197 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_SIZE (type));
198 omp_firstprivatize_variable (ctx, GFC_TYPE_ARRAY_OFFSET (type));
204 gfc_trans_add_clause (tree node, tree tail)
206 OMP_CLAUSE_CHAIN (node) = tail;
211 gfc_trans_omp_variable (gfc_symbol *sym)
213 tree t = gfc_get_symbol_decl (sym);
217 bool alternate_entry;
220 return_value = sym->attr.function && sym->result == sym;
221 alternate_entry = sym->attr.function && sym->attr.entry
222 && sym->result == sym;
223 entry_master = sym->attr.result
224 && sym->ns->proc_name->attr.entry_master
225 && !gfc_return_by_reference (sym->ns->proc_name);
226 parent_decl = DECL_CONTEXT (current_function_decl);
228 if ((t == parent_decl && return_value)
229 || (sym->ns && sym->ns->proc_name
230 && sym->ns->proc_name->backend_decl == parent_decl
231 && (alternate_entry || entry_master)))
236 /* Special case for assigning the return value of a function.
237 Self recursive functions must have an explicit return value. */
238 if (return_value && (t == current_function_decl || parent_flag))
239 t = gfc_get_fake_result_decl (sym, parent_flag);
241 /* Similarly for alternate entry points. */
242 else if (alternate_entry
243 && (sym->ns->proc_name->backend_decl == current_function_decl
246 gfc_entry_list *el = NULL;
248 for (el = sym->ns->entries; el; el = el->next)
251 t = gfc_get_fake_result_decl (sym, parent_flag);
256 else if (entry_master
257 && (sym->ns->proc_name->backend_decl == current_function_decl
259 t = gfc_get_fake_result_decl (sym, parent_flag);
265 gfc_trans_omp_variable_list (enum omp_clause_code code, gfc_namelist *namelist,
268 for (; namelist != NULL; namelist = namelist->next)
269 if (namelist->sym->attr.referenced)
271 tree t = gfc_trans_omp_variable (namelist->sym);
272 if (t != error_mark_node)
274 tree node = build_omp_clause (code);
275 OMP_CLAUSE_DECL (node) = t;
276 list = gfc_trans_add_clause (node, list);
283 gfc_trans_omp_array_reduction (tree c, gfc_symbol *sym, locus where)
285 gfc_symtree *root1 = NULL, *root2 = NULL, *root3 = NULL, *root4 = NULL;
286 gfc_symtree *symtree1, *symtree2, *symtree3, *symtree4 = NULL;
287 gfc_symbol init_val_sym, outer_sym, intrinsic_sym;
288 gfc_expr *e1, *e2, *e3, *e4;
290 tree decl, backend_decl, stmt;
291 locus old_loc = gfc_current_locus;
295 decl = OMP_CLAUSE_DECL (c);
296 gfc_current_locus = where;
298 /* Create a fake symbol for init value. */
299 memset (&init_val_sym, 0, sizeof (init_val_sym));
300 init_val_sym.ns = sym->ns;
301 init_val_sym.name = sym->name;
302 init_val_sym.ts = sym->ts;
303 init_val_sym.attr.referenced = 1;
304 init_val_sym.declared_at = where;
305 init_val_sym.attr.flavor = FL_VARIABLE;
306 backend_decl = omp_reduction_init (c, gfc_sym_type (&init_val_sym));
307 init_val_sym.backend_decl = backend_decl;
309 /* Create a fake symbol for the outer array reference. */
311 outer_sym.as = gfc_copy_array_spec (sym->as);
312 outer_sym.attr.dummy = 0;
313 outer_sym.attr.result = 0;
314 outer_sym.attr.flavor = FL_VARIABLE;
315 outer_sym.backend_decl = create_tmp_var_raw (TREE_TYPE (decl), NULL);
317 /* Create fake symtrees for it. */
318 symtree1 = gfc_new_symtree (&root1, sym->name);
319 symtree1->n.sym = sym;
320 gcc_assert (symtree1 == root1);
322 symtree2 = gfc_new_symtree (&root2, sym->name);
323 symtree2->n.sym = &init_val_sym;
324 gcc_assert (symtree2 == root2);
326 symtree3 = gfc_new_symtree (&root3, sym->name);
327 symtree3->n.sym = &outer_sym;
328 gcc_assert (symtree3 == root3);
330 /* Create expressions. */
331 e1 = gfc_get_expr ();
332 e1->expr_type = EXPR_VARIABLE;
334 e1->symtree = symtree1;
336 e1->ref = ref = gfc_get_ref ();
337 ref->u.ar.where = where;
338 ref->u.ar.as = sym->as;
339 ref->u.ar.type = AR_FULL;
341 t = gfc_resolve_expr (e1);
342 gcc_assert (t == SUCCESS);
344 e2 = gfc_get_expr ();
345 e2->expr_type = EXPR_VARIABLE;
347 e2->symtree = symtree2;
349 t = gfc_resolve_expr (e2);
350 gcc_assert (t == SUCCESS);
352 e3 = gfc_copy_expr (e1);
353 e3->symtree = symtree3;
354 t = gfc_resolve_expr (e3);
355 gcc_assert (t == SUCCESS);
358 switch (OMP_CLAUSE_REDUCTION_CODE (c))
362 e4 = gfc_add (e3, e1);
365 e4 = gfc_multiply (e3, e1);
367 case TRUTH_ANDIF_EXPR:
368 e4 = gfc_and (e3, e1);
370 case TRUTH_ORIF_EXPR:
371 e4 = gfc_or (e3, e1);
374 e4 = gfc_eqv (e3, e1);
377 e4 = gfc_neqv (e3, e1);
399 memset (&intrinsic_sym, 0, sizeof (intrinsic_sym));
400 intrinsic_sym.ns = sym->ns;
401 intrinsic_sym.name = iname;
402 intrinsic_sym.ts = sym->ts;
403 intrinsic_sym.attr.referenced = 1;
404 intrinsic_sym.attr.intrinsic = 1;
405 intrinsic_sym.attr.function = 1;
406 intrinsic_sym.result = &intrinsic_sym;
407 intrinsic_sym.declared_at = where;
409 symtree4 = gfc_new_symtree (&root4, iname);
410 symtree4->n.sym = &intrinsic_sym;
411 gcc_assert (symtree4 == root4);
413 e4 = gfc_get_expr ();
414 e4->expr_type = EXPR_FUNCTION;
416 e4->symtree = symtree4;
417 e4->value.function.isym = gfc_find_function (iname);
418 e4->value.function.actual = gfc_get_actual_arglist ();
419 e4->value.function.actual->expr = e3;
420 e4->value.function.actual->next = gfc_get_actual_arglist ();
421 e4->value.function.actual->next->expr = e1;
423 /* e1 and e3 have been stored as arguments of e4, avoid sharing. */
424 e1 = gfc_copy_expr (e1);
425 e3 = gfc_copy_expr (e3);
426 t = gfc_resolve_expr (e4);
427 gcc_assert (t == SUCCESS);
429 /* Create the init statement list. */
431 stmt = gfc_trans_assignment (e1, e2, false);
432 if (TREE_CODE (stmt) != BIND_EXPR)
433 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
436 OMP_CLAUSE_REDUCTION_INIT (c) = stmt;
438 /* Create the merge statement list. */
440 stmt = gfc_trans_assignment (e3, e4, false);
441 if (TREE_CODE (stmt) != BIND_EXPR)
442 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
445 OMP_CLAUSE_REDUCTION_MERGE (c) = stmt;
447 /* And stick the placeholder VAR_DECL into the clause as well. */
448 OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = outer_sym.backend_decl;
450 gfc_current_locus = old_loc;
461 gfc_free_array_spec (outer_sym.as);
465 gfc_trans_omp_reduction_list (gfc_namelist *namelist, tree list,
466 enum tree_code reduction_code, locus where)
468 for (; namelist != NULL; namelist = namelist->next)
469 if (namelist->sym->attr.referenced)
471 tree t = gfc_trans_omp_variable (namelist->sym);
472 if (t != error_mark_node)
474 tree node = build_omp_clause (OMP_CLAUSE_REDUCTION);
475 OMP_CLAUSE_DECL (node) = t;
476 OMP_CLAUSE_REDUCTION_CODE (node) = reduction_code;
477 if (namelist->sym->attr.dimension)
478 gfc_trans_omp_array_reduction (node, namelist->sym, where);
479 list = gfc_trans_add_clause (node, list);
486 gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
489 tree omp_clauses = NULL_TREE, chunk_size, c, old_clauses;
491 enum omp_clause_code clause_code;
497 for (list = 0; list < OMP_LIST_NUM; list++)
499 gfc_namelist *n = clauses->lists[list];
503 if (list >= OMP_LIST_REDUCTION_FIRST
504 && list <= OMP_LIST_REDUCTION_LAST)
506 enum tree_code reduction_code;
510 reduction_code = PLUS_EXPR;
513 reduction_code = MULT_EXPR;
516 reduction_code = MINUS_EXPR;
519 reduction_code = TRUTH_ANDIF_EXPR;
522 reduction_code = TRUTH_ORIF_EXPR;
525 reduction_code = EQ_EXPR;
528 reduction_code = NE_EXPR;
531 reduction_code = MAX_EXPR;
534 reduction_code = MIN_EXPR;
537 reduction_code = BIT_AND_EXPR;
540 reduction_code = BIT_IOR_EXPR;
543 reduction_code = BIT_XOR_EXPR;
548 old_clauses = omp_clauses;
550 = gfc_trans_omp_reduction_list (n, omp_clauses, reduction_code,
556 case OMP_LIST_PRIVATE:
557 clause_code = OMP_CLAUSE_PRIVATE;
559 case OMP_LIST_SHARED:
560 clause_code = OMP_CLAUSE_SHARED;
562 case OMP_LIST_FIRSTPRIVATE:
563 clause_code = OMP_CLAUSE_FIRSTPRIVATE;
565 case OMP_LIST_LASTPRIVATE:
566 clause_code = OMP_CLAUSE_LASTPRIVATE;
568 case OMP_LIST_COPYIN:
569 clause_code = OMP_CLAUSE_COPYIN;
571 case OMP_LIST_COPYPRIVATE:
572 clause_code = OMP_CLAUSE_COPYPRIVATE;
576 = gfc_trans_omp_variable_list (clause_code, n, omp_clauses);
583 if (clauses->if_expr)
587 gfc_init_se (&se, NULL);
588 gfc_conv_expr (&se, clauses->if_expr);
589 gfc_add_block_to_block (block, &se.pre);
590 if_var = gfc_evaluate_now (se.expr, block);
591 gfc_add_block_to_block (block, &se.post);
593 c = build_omp_clause (OMP_CLAUSE_IF);
594 OMP_CLAUSE_IF_EXPR (c) = if_var;
595 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
598 if (clauses->num_threads)
602 gfc_init_se (&se, NULL);
603 gfc_conv_expr (&se, clauses->num_threads);
604 gfc_add_block_to_block (block, &se.pre);
605 num_threads = gfc_evaluate_now (se.expr, block);
606 gfc_add_block_to_block (block, &se.post);
608 c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
609 OMP_CLAUSE_NUM_THREADS_EXPR (c) = num_threads;
610 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
613 chunk_size = NULL_TREE;
614 if (clauses->chunk_size)
616 gfc_init_se (&se, NULL);
617 gfc_conv_expr (&se, clauses->chunk_size);
618 gfc_add_block_to_block (block, &se.pre);
619 chunk_size = gfc_evaluate_now (se.expr, block);
620 gfc_add_block_to_block (block, &se.post);
623 if (clauses->sched_kind != OMP_SCHED_NONE)
625 c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
626 OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = chunk_size;
627 switch (clauses->sched_kind)
629 case OMP_SCHED_STATIC:
630 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
632 case OMP_SCHED_DYNAMIC:
633 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
635 case OMP_SCHED_GUIDED:
636 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
638 case OMP_SCHED_RUNTIME:
639 OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
644 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
647 if (clauses->default_sharing != OMP_DEFAULT_UNKNOWN)
649 c = build_omp_clause (OMP_CLAUSE_DEFAULT);
650 switch (clauses->default_sharing)
652 case OMP_DEFAULT_NONE:
653 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_NONE;
655 case OMP_DEFAULT_SHARED:
656 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_SHARED;
658 case OMP_DEFAULT_PRIVATE:
659 OMP_CLAUSE_DEFAULT_KIND (c) = OMP_CLAUSE_DEFAULT_PRIVATE;
664 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
669 c = build_omp_clause (OMP_CLAUSE_NOWAIT);
670 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
673 if (clauses->ordered)
675 c = build_omp_clause (OMP_CLAUSE_ORDERED);
676 omp_clauses = gfc_trans_add_clause (c, omp_clauses);
682 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
685 gfc_trans_omp_code (gfc_code *code, bool force_empty)
690 stmt = gfc_trans_code (code);
691 if (TREE_CODE (stmt) != BIND_EXPR)
693 if (!IS_EMPTY_STMT (stmt) || force_empty)
695 tree block = poplevel (1, 0, 0);
696 stmt = build3_v (BIND_EXPR, NULL, stmt, block);
707 static tree gfc_trans_omp_sections (gfc_code *, gfc_omp_clauses *);
708 static tree gfc_trans_omp_workshare (gfc_code *, gfc_omp_clauses *);
711 gfc_trans_omp_atomic (gfc_code *code)
718 tree lhsaddr, type, rhs, x;
719 enum tree_code op = ERROR_MARK;
720 bool var_on_left = false;
722 code = code->block->next;
723 gcc_assert (code->op == EXEC_ASSIGN);
724 gcc_assert (code->next == NULL);
725 var = code->expr->symtree->n.sym;
727 gfc_init_se (&lse, NULL);
728 gfc_init_se (&rse, NULL);
729 gfc_start_block (&block);
731 gfc_conv_expr (&lse, code->expr);
732 gfc_add_block_to_block (&block, &lse.pre);
733 type = TREE_TYPE (lse.expr);
734 lhsaddr = gfc_build_addr_expr (NULL, lse.expr);
737 if (expr2->expr_type == EXPR_FUNCTION
738 && expr2->value.function.isym->id == GFC_ISYM_CONVERSION)
739 expr2 = expr2->value.function.actual->expr;
741 if (expr2->expr_type == EXPR_OP)
744 switch (expr2->value.op.operator)
749 case INTRINSIC_TIMES:
752 case INTRINSIC_MINUS:
755 case INTRINSIC_DIVIDE:
756 if (expr2->ts.type == BT_INTEGER)
762 op = TRUTH_ANDIF_EXPR;
765 op = TRUTH_ORIF_EXPR;
776 e = expr2->value.op.op1;
777 if (e->expr_type == EXPR_FUNCTION
778 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
779 e = e->value.function.actual->expr;
780 if (e->expr_type == EXPR_VARIABLE
781 && e->symtree != NULL
782 && e->symtree->n.sym == var)
784 expr2 = expr2->value.op.op2;
789 e = expr2->value.op.op2;
790 if (e->expr_type == EXPR_FUNCTION
791 && e->value.function.isym->id == GFC_ISYM_CONVERSION)
792 e = e->value.function.actual->expr;
793 gcc_assert (e->expr_type == EXPR_VARIABLE
794 && e->symtree != NULL
795 && e->symtree->n.sym == var);
796 expr2 = expr2->value.op.op1;
799 gfc_conv_expr (&rse, expr2);
800 gfc_add_block_to_block (&block, &rse.pre);
804 gcc_assert (expr2->expr_type == EXPR_FUNCTION);
805 switch (expr2->value.function.isym->id)
825 e = expr2->value.function.actual->expr;
826 gcc_assert (e->expr_type == EXPR_VARIABLE
827 && e->symtree != NULL
828 && e->symtree->n.sym == var);
830 gfc_conv_expr (&rse, expr2->value.function.actual->next->expr);
831 gfc_add_block_to_block (&block, &rse.pre);
832 if (expr2->value.function.actual->next->next != NULL)
834 tree accum = gfc_create_var (TREE_TYPE (rse.expr), NULL);
835 gfc_actual_arglist *arg;
837 gfc_add_modify_stmt (&block, accum, rse.expr);
838 for (arg = expr2->value.function.actual->next->next; arg;
841 gfc_init_block (&rse.pre);
842 gfc_conv_expr (&rse, arg->expr);
843 gfc_add_block_to_block (&block, &rse.pre);
844 x = fold_build2 (op, TREE_TYPE (accum), accum, rse.expr);
845 gfc_add_modify_stmt (&block, accum, x);
851 expr2 = expr2->value.function.actual->next->expr;
854 lhsaddr = save_expr (lhsaddr);
855 rhs = gfc_evaluate_now (rse.expr, &block);
856 x = convert (TREE_TYPE (rhs), build_fold_indirect_ref (lhsaddr));
859 x = fold_build2 (op, TREE_TYPE (rhs), x, rhs);
861 x = fold_build2 (op, TREE_TYPE (rhs), rhs, x);
863 if (TREE_CODE (TREE_TYPE (rhs)) == COMPLEX_TYPE
864 && TREE_CODE (type) != COMPLEX_TYPE)
865 x = build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (rhs)), x);
867 x = build2_v (OMP_ATOMIC, lhsaddr, convert (type, x));
868 gfc_add_expr_to_block (&block, x);
870 gfc_add_block_to_block (&block, &lse.pre);
871 gfc_add_block_to_block (&block, &rse.pre);
873 return gfc_finish_block (&block);
877 gfc_trans_omp_barrier (void)
879 tree decl = built_in_decls [BUILT_IN_GOMP_BARRIER];
880 return build_call_expr (decl, 0);
884 gfc_trans_omp_critical (gfc_code *code)
886 tree name = NULL_TREE, stmt;
887 if (code->ext.omp_name != NULL)
888 name = get_identifier (code->ext.omp_name);
889 stmt = gfc_trans_code (code->block->next);
890 return build2_v (OMP_CRITICAL, stmt, name);
894 gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock,
895 gfc_omp_clauses *do_clauses)
898 tree dovar, stmt, from, to, step, type, init, cond, incr;
899 tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
903 bool dovar_found = false;
904 gfc_omp_clauses *clauses = code->ext.omp_clauses;
906 code = code->block->next;
907 gcc_assert (code->op == EXEC_DO);
911 gfc_start_block (&block);
915 omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
919 for (n = clauses->lists[OMP_LIST_LASTPRIVATE]; n != NULL; n = n->next)
920 if (code->ext.iterator->var->symtree->n.sym == n->sym)
923 for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next)
924 if (code->ext.iterator->var->symtree->n.sym == n->sym)
930 /* Evaluate all the expressions in the iterator. */
931 gfc_init_se (&se, NULL);
932 gfc_conv_expr_lhs (&se, code->ext.iterator->var);
933 gfc_add_block_to_block (pblock, &se.pre);
935 type = TREE_TYPE (dovar);
936 gcc_assert (TREE_CODE (type) == INTEGER_TYPE);
938 gfc_init_se (&se, NULL);
939 gfc_conv_expr_val (&se, code->ext.iterator->start);
940 gfc_add_block_to_block (pblock, &se.pre);
941 from = gfc_evaluate_now (se.expr, pblock);
943 gfc_init_se (&se, NULL);
944 gfc_conv_expr_val (&se, code->ext.iterator->end);
945 gfc_add_block_to_block (pblock, &se.pre);
946 to = gfc_evaluate_now (se.expr, pblock);
948 gfc_init_se (&se, NULL);
949 gfc_conv_expr_val (&se, code->ext.iterator->step);
950 gfc_add_block_to_block (pblock, &se.pre);
951 step = gfc_evaluate_now (se.expr, pblock);
953 /* Special case simple loops. */
954 if (integer_onep (step))
956 else if (tree_int_cst_equal (step, integer_minus_one_node))
962 init = build2_v (GIMPLE_MODIFY_STMT, dovar, from);
963 cond = build2 (simple > 0 ? LE_EXPR : GE_EXPR, boolean_type_node,
965 incr = fold_build2 (PLUS_EXPR, type, dovar, step);
966 incr = fold_build2 (GIMPLE_MODIFY_STMT, type, dovar, incr);
967 if (pblock != &block)
970 gfc_start_block (&block);
972 gfc_start_block (&body);
976 /* STEP is not 1 or -1. Use:
977 for (count = 0; count < (to + step - from) / step; count++)
979 dovar = from + count * step;
983 tmp = fold_build2 (MINUS_EXPR, type, step, from);
984 tmp = fold_build2 (PLUS_EXPR, type, to, tmp);
985 tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step);
986 tmp = gfc_evaluate_now (tmp, pblock);
987 count = gfc_create_var (type, "count");
988 init = build2_v (GIMPLE_MODIFY_STMT, count, build_int_cst (type, 0));
989 cond = build2 (LT_EXPR, boolean_type_node, count, tmp);
990 incr = fold_build2 (PLUS_EXPR, type, count, build_int_cst (type, 1));
991 incr = fold_build2 (GIMPLE_MODIFY_STMT, type, count, incr);
993 if (pblock != &block)
996 gfc_start_block (&block);
998 gfc_start_block (&body);
1000 /* Initialize DOVAR. */
1001 tmp = fold_build2 (MULT_EXPR, type, count, step);
1002 tmp = build2 (PLUS_EXPR, type, from, tmp);
1003 gfc_add_modify_stmt (&body, dovar, tmp);
1008 tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
1009 OMP_CLAUSE_DECL (tmp) = dovar;
1010 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
1014 tmp = build_omp_clause (OMP_CLAUSE_PRIVATE);
1015 OMP_CLAUSE_DECL (tmp) = count;
1016 omp_clauses = gfc_trans_add_clause (tmp, omp_clauses);
1019 /* Cycle statement is implemented with a goto. Exit statement must not be
1020 present for this loop. */
1021 cycle_label = gfc_build_label_decl (NULL_TREE);
1023 /* Put these labels where they can be found later. We put the
1024 labels in a TREE_LIST node (because TREE_CHAIN is already
1025 used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
1026 label in TREE_VALUE (backend_decl). */
1028 code->block->backend_decl = tree_cons (cycle_label, NULL, NULL);
1030 /* Main loop body. */
1031 tmp = gfc_trans_omp_code (code->block->next, true);
1032 gfc_add_expr_to_block (&body, tmp);
1034 /* Label for cycle statements (if needed). */
1035 if (TREE_USED (cycle_label))
1037 tmp = build1_v (LABEL_EXPR, cycle_label);
1038 gfc_add_expr_to_block (&body, tmp);
1041 /* End of loop body. */
1042 stmt = make_node (OMP_FOR);
1044 TREE_TYPE (stmt) = void_type_node;
1045 OMP_FOR_BODY (stmt) = gfc_finish_block (&body);
1046 OMP_FOR_CLAUSES (stmt) = omp_clauses;
1047 OMP_FOR_INIT (stmt) = init;
1048 OMP_FOR_COND (stmt) = cond;
1049 OMP_FOR_INCR (stmt) = incr;
1050 gfc_add_expr_to_block (&block, stmt);
1052 return gfc_finish_block (&block);
1056 gfc_trans_omp_flush (void)
1058 tree decl = built_in_decls [BUILT_IN_SYNCHRONIZE];
1059 return build_call_expr (decl, 0);
1063 gfc_trans_omp_master (gfc_code *code)
1065 tree stmt = gfc_trans_code (code->block->next);
1066 if (IS_EMPTY_STMT (stmt))
1068 return build1_v (OMP_MASTER, stmt);
1072 gfc_trans_omp_ordered (gfc_code *code)
1074 return build1_v (OMP_ORDERED, gfc_trans_code (code->block->next));
1078 gfc_trans_omp_parallel (gfc_code *code)
1081 tree stmt, omp_clauses;
1083 gfc_start_block (&block);
1084 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1086 stmt = gfc_trans_omp_code (code->block->next, true);
1087 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1088 gfc_add_expr_to_block (&block, stmt);
1089 return gfc_finish_block (&block);
1093 gfc_trans_omp_parallel_do (gfc_code *code)
1095 stmtblock_t block, *pblock = NULL;
1096 gfc_omp_clauses parallel_clauses, do_clauses;
1097 tree stmt, omp_clauses = NULL_TREE;
1099 gfc_start_block (&block);
1101 memset (&do_clauses, 0, sizeof (do_clauses));
1102 if (code->ext.omp_clauses != NULL)
1104 memcpy (¶llel_clauses, code->ext.omp_clauses,
1105 sizeof (parallel_clauses));
1106 do_clauses.sched_kind = parallel_clauses.sched_kind;
1107 do_clauses.chunk_size = parallel_clauses.chunk_size;
1108 do_clauses.ordered = parallel_clauses.ordered;
1109 parallel_clauses.sched_kind = OMP_SCHED_NONE;
1110 parallel_clauses.chunk_size = NULL;
1111 parallel_clauses.ordered = false;
1112 omp_clauses = gfc_trans_omp_clauses (&block, ¶llel_clauses,
1115 do_clauses.nowait = true;
1116 if (!do_clauses.ordered && do_clauses.sched_kind != OMP_SCHED_STATIC)
1120 stmt = gfc_trans_omp_do (code, pblock, &do_clauses);
1121 if (TREE_CODE (stmt) != BIND_EXPR)
1122 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1125 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1126 OMP_PARALLEL_COMBINED (stmt) = 1;
1127 gfc_add_expr_to_block (&block, stmt);
1128 return gfc_finish_block (&block);
1132 gfc_trans_omp_parallel_sections (gfc_code *code)
1135 gfc_omp_clauses section_clauses;
1136 tree stmt, omp_clauses;
1138 memset (§ion_clauses, 0, sizeof (section_clauses));
1139 section_clauses.nowait = true;
1141 gfc_start_block (&block);
1142 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1145 stmt = gfc_trans_omp_sections (code, §ion_clauses);
1146 if (TREE_CODE (stmt) != BIND_EXPR)
1147 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1150 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1151 OMP_PARALLEL_COMBINED (stmt) = 1;
1152 gfc_add_expr_to_block (&block, stmt);
1153 return gfc_finish_block (&block);
1157 gfc_trans_omp_parallel_workshare (gfc_code *code)
1160 gfc_omp_clauses workshare_clauses;
1161 tree stmt, omp_clauses;
1163 memset (&workshare_clauses, 0, sizeof (workshare_clauses));
1164 workshare_clauses.nowait = true;
1166 gfc_start_block (&block);
1167 omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
1170 stmt = gfc_trans_omp_workshare (code, &workshare_clauses);
1171 if (TREE_CODE (stmt) != BIND_EXPR)
1172 stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0, 0));
1175 stmt = build4_v (OMP_PARALLEL, stmt, omp_clauses, NULL, NULL);
1176 OMP_PARALLEL_COMBINED (stmt) = 1;
1177 gfc_add_expr_to_block (&block, stmt);
1178 return gfc_finish_block (&block);
1182 gfc_trans_omp_sections (gfc_code *code, gfc_omp_clauses *clauses)
1184 stmtblock_t block, body;
1185 tree omp_clauses, stmt;
1186 bool has_lastprivate = clauses->lists[OMP_LIST_LASTPRIVATE] != NULL;
1188 gfc_start_block (&block);
1190 omp_clauses = gfc_trans_omp_clauses (&block, clauses, code->loc);
1192 gfc_init_block (&body);
1193 for (code = code->block; code; code = code->block)
1195 /* Last section is special because of lastprivate, so even if it
1196 is empty, chain it in. */
1197 stmt = gfc_trans_omp_code (code->next,
1198 has_lastprivate && code->block == NULL);
1199 if (! IS_EMPTY_STMT (stmt))
1201 stmt = build1_v (OMP_SECTION, stmt);
1202 gfc_add_expr_to_block (&body, stmt);
1205 stmt = gfc_finish_block (&body);
1207 stmt = build3_v (OMP_SECTIONS, stmt, omp_clauses, NULL_TREE);
1208 gfc_add_expr_to_block (&block, stmt);
1210 return gfc_finish_block (&block);
1214 gfc_trans_omp_single (gfc_code *code, gfc_omp_clauses *clauses)
1216 tree omp_clauses = gfc_trans_omp_clauses (NULL, clauses, code->loc);
1217 tree stmt = gfc_trans_omp_code (code->block->next, true);
1218 stmt = build2_v (OMP_SINGLE, stmt, omp_clauses);
1223 gfc_trans_omp_workshare (gfc_code *code, gfc_omp_clauses *clauses)
1226 return gfc_trans_omp_single (code, clauses);
1230 gfc_trans_omp_directive (gfc_code *code)
1234 case EXEC_OMP_ATOMIC:
1235 return gfc_trans_omp_atomic (code);
1236 case EXEC_OMP_BARRIER:
1237 return gfc_trans_omp_barrier ();
1238 case EXEC_OMP_CRITICAL:
1239 return gfc_trans_omp_critical (code);
1241 return gfc_trans_omp_do (code, NULL, code->ext.omp_clauses);
1242 case EXEC_OMP_FLUSH:
1243 return gfc_trans_omp_flush ();
1244 case EXEC_OMP_MASTER:
1245 return gfc_trans_omp_master (code);
1246 case EXEC_OMP_ORDERED:
1247 return gfc_trans_omp_ordered (code);
1248 case EXEC_OMP_PARALLEL:
1249 return gfc_trans_omp_parallel (code);
1250 case EXEC_OMP_PARALLEL_DO:
1251 return gfc_trans_omp_parallel_do (code);
1252 case EXEC_OMP_PARALLEL_SECTIONS:
1253 return gfc_trans_omp_parallel_sections (code);
1254 case EXEC_OMP_PARALLEL_WORKSHARE:
1255 return gfc_trans_omp_parallel_workshare (code);
1256 case EXEC_OMP_SECTIONS:
1257 return gfc_trans_omp_sections (code, code->ext.omp_clauses);
1258 case EXEC_OMP_SINGLE:
1259 return gfc_trans_omp_single (code, code->ext.omp_clauses);
1260 case EXEC_OMP_WORKSHARE:
1261 return gfc_trans_omp_workshare (code, code->ext.omp_clauses);