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
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 COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
25 #include "coretypes.h"
27 #include "tree-gimple.h"
33 #include "trans-stmt.h"
34 #include "trans-types.h"
35 #include "trans-array.h"
36 #include "trans-const.h"
40 /* True if OpenMP should privatize what this DECL points to rather
41 than the DECL itself. */
44 gfc_omp_privatize_by_reference (tree decl
)
46 tree type
= TREE_TYPE (decl
);
48 if (TREE_CODE (type
) == REFERENCE_TYPE
)
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
56 if (!DECL_ARTIFICIAL (decl
))
59 /* Some arrays are expanded as DECL_ARTIFICIAL pointers
61 if (DECL_LANG_SPECIFIC (decl
)
62 && GFC_DECL_SAVED_DESCRIPTOR (decl
))
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
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. */
102 gfc_omp_clause_default_ctor (tree clause ATTRIBUTE_UNUSED
, tree decl
)
104 tree type
= TREE_TYPE (decl
);
107 if (! GFC_DESCRIPTOR_TYPE_P (type
))
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. */
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. */
148 if (GFC_DECL_RESULT (decl
) && DECL_HAS_VALUE_EXPR_P (decl
))
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
159 gfc_omp_private_debug_clause (tree decl
, bool shared
)
161 if (GFC_DECL_CRAY_POINTEE (decl
))
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)))
178 /* Register language specific type size variables as potentially OpenMP
179 firstprivate variables. */
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
))
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
));
202 gfc_trans_add_clause (tree node
, tree tail
)
204 OMP_CLAUSE_CHAIN (node
) = tail
;
209 gfc_trans_omp_variable (gfc_symbol
*sym
)
211 tree t
= gfc_get_symbol_decl (sym
);
215 bool alternate_entry
;
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
)))
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
244 gfc_entry_list
*el
= NULL
;
246 for (el
= sym
->ns
->entries
; el
; el
= el
->next
)
249 t
= gfc_get_fake_result_decl (sym
, parent_flag
);
254 else if (entry_master
255 && (sym
->ns
->proc_name
->backend_decl
== current_function_decl
257 t
= gfc_get_fake_result_decl (sym
, parent_flag
);
263 gfc_trans_omp_variable_list (enum omp_clause_code code
, gfc_namelist
*namelist
,
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
);
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
;
288 tree decl
, backend_decl
, stmt
;
289 locus old_loc
= gfc_current_locus
;
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. */
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
;
330 e1
->symtree
= symtree1
;
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
;
337 t
= gfc_resolve_expr (e1
);
338 gcc_assert (t
== SUCCESS
);
340 e2
= gfc_get_expr ();
341 e2
->expr_type
= EXPR_VARIABLE
;
343 e2
->symtree
= symtree2
;
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
);
354 switch (OMP_CLAUSE_REDUCTION_CODE (c
))
358 e4
= gfc_add (e3
, e1
);
361 e4
= gfc_multiply (e3
, e1
);
363 case TRUTH_ANDIF_EXPR
:
364 e4
= gfc_and (e3
, e1
);
366 case TRUTH_ORIF_EXPR
:
367 e4
= gfc_or (e3
, e1
);
370 e4
= gfc_eqv (e3
, e1
);
373 e4
= gfc_neqv (e3
, e1
);
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
;
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. */
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));
432 OMP_CLAUSE_REDUCTION_INIT (c
) = stmt
;
434 /* Create the merge statement list. */
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));
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
;
457 gfc_free_array_spec (outer_sym
.as
);
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
);
482 gfc_trans_omp_clauses (stmtblock_t
*block
, gfc_omp_clauses
*clauses
,
485 tree omp_clauses
= NULL_TREE
, chunk_size
, c
, old_clauses
;
487 enum omp_clause_code clause_code
;
493 for (list
= 0; list
< OMP_LIST_NUM
; list
++)
495 gfc_namelist
*n
= clauses
->lists
[list
];
499 if (list
>= OMP_LIST_REDUCTION_FIRST
500 && list
<= OMP_LIST_REDUCTION_LAST
)
502 enum tree_code reduction_code
;
506 reduction_code
= PLUS_EXPR
;
509 reduction_code
= MULT_EXPR
;
512 reduction_code
= MINUS_EXPR
;
515 reduction_code
= TRUTH_ANDIF_EXPR
;
518 reduction_code
= TRUTH_ORIF_EXPR
;
521 reduction_code
= EQ_EXPR
;
524 reduction_code
= NE_EXPR
;
527 reduction_code
= MAX_EXPR
;
530 reduction_code
= MIN_EXPR
;
533 reduction_code
= BIT_AND_EXPR
;
536 reduction_code
= BIT_IOR_EXPR
;
539 reduction_code
= BIT_XOR_EXPR
;
544 old_clauses
= omp_clauses
;
546 = gfc_trans_omp_reduction_list (n
, omp_clauses
, reduction_code
,
552 case OMP_LIST_PRIVATE
:
553 clause_code
= OMP_CLAUSE_PRIVATE
;
555 case OMP_LIST_SHARED
:
556 clause_code
= OMP_CLAUSE_SHARED
;
558 case OMP_LIST_FIRSTPRIVATE
:
559 clause_code
= OMP_CLAUSE_FIRSTPRIVATE
;
561 case OMP_LIST_LASTPRIVATE
:
562 clause_code
= OMP_CLAUSE_LASTPRIVATE
;
564 case OMP_LIST_COPYIN
:
565 clause_code
= OMP_CLAUSE_COPYIN
;
567 case OMP_LIST_COPYPRIVATE
:
568 clause_code
= OMP_CLAUSE_COPYPRIVATE
;
572 = gfc_trans_omp_variable_list (clause_code
, n
, omp_clauses
);
579 if (clauses
->if_expr
)
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
)
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
;
628 case OMP_SCHED_DYNAMIC
:
629 OMP_CLAUSE_SCHEDULE_KIND (c
) = OMP_CLAUSE_SCHEDULE_DYNAMIC
;
631 case OMP_SCHED_GUIDED
:
632 OMP_CLAUSE_SCHEDULE_KIND (c
) = OMP_CLAUSE_SCHEDULE_GUIDED
;
634 case OMP_SCHED_RUNTIME
:
635 OMP_CLAUSE_SCHEDULE_KIND (c
) = OMP_CLAUSE_SCHEDULE_RUNTIME
;
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
;
651 case OMP_DEFAULT_SHARED
:
652 OMP_CLAUSE_DEFAULT_KIND (c
) = OMP_CLAUSE_DEFAULT_SHARED
;
654 case OMP_DEFAULT_PRIVATE
:
655 OMP_CLAUSE_DEFAULT_KIND (c
) = OMP_CLAUSE_DEFAULT_PRIVATE
;
660 omp_clauses
= gfc_trans_add_clause (c
, omp_clauses
);
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
);
678 /* Like gfc_trans_code, but force creation of a BIND_EXPR around it. */
681 gfc_trans_omp_code (gfc_code
*code
, bool force_empty
)
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
);
703 static tree
gfc_trans_omp_sections (gfc_code
*, gfc_omp_clauses
*);
704 static tree
gfc_trans_omp_workshare (gfc_code
*, gfc_omp_clauses
*);
707 gfc_trans_omp_atomic (gfc_code
*code
)
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
);
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
)
740 switch (expr2
->value
.op
.operator)
745 case INTRINSIC_TIMES
:
748 case INTRINSIC_MINUS
:
751 case INTRINSIC_DIVIDE
:
752 if (expr2
->ts
.type
== BT_INTEGER
)
758 op
= TRUTH_ANDIF_EXPR
;
761 op
= TRUTH_ORIF_EXPR
;
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
;
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
;
795 gfc_conv_expr (&rse
, expr2
);
796 gfc_add_block_to_block (&block
, &rse
.pre
);
800 gcc_assert (expr2
->expr_type
== EXPR_FUNCTION
);
801 switch (expr2
->value
.function
.isym
->generic_id
)
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
;
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
);
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
));
855 x
= fold_build2 (op
, TREE_TYPE (rhs
), x
, rhs
);
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
);
873 gfc_trans_omp_barrier (void)
875 tree decl
= built_in_decls
[BUILT_IN_GOMP_BARRIER
];
876 return build_function_call_expr (decl
, NULL
);
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
);
890 gfc_trans_omp_do (gfc_code
*code
, stmtblock_t
*pblock
,
891 gfc_omp_clauses
*clauses
)
894 tree dovar
, stmt
, from
, to
, step
, type
, init
, cond
, incr
;
895 tree count
= NULL_TREE
, cycle_label
, tmp
, omp_clauses
;
899 bool dovar_found
= false;
901 code
= code
->block
->next
;
902 gcc_assert (code
->op
== EXEC_DO
);
906 gfc_start_block (&block
);
910 omp_clauses
= gfc_trans_omp_clauses (pblock
, clauses
, code
->loc
);
914 for (n
= clauses
->lists
[OMP_LIST_LASTPRIVATE
]; n
!= NULL
; n
= n
->next
)
915 if (code
->ext
.iterator
->var
->symtree
->n
.sym
== n
->sym
)
918 for (n
= clauses
->lists
[OMP_LIST_PRIVATE
]; n
!= NULL
; n
= n
->next
)
919 if (code
->ext
.iterator
->var
->symtree
->n
.sym
== n
->sym
)
925 /* Evaluate all the expressions in the iterator. */
926 gfc_init_se (&se
, NULL
);
927 gfc_conv_expr_lhs (&se
, code
->ext
.iterator
->var
);
928 gfc_add_block_to_block (pblock
, &se
.pre
);
930 type
= TREE_TYPE (dovar
);
931 gcc_assert (TREE_CODE (type
) == INTEGER_TYPE
);
933 gfc_init_se (&se
, NULL
);
934 gfc_conv_expr_val (&se
, code
->ext
.iterator
->start
);
935 gfc_add_block_to_block (pblock
, &se
.pre
);
936 from
= gfc_evaluate_now (se
.expr
, pblock
);
938 gfc_init_se (&se
, NULL
);
939 gfc_conv_expr_val (&se
, code
->ext
.iterator
->end
);
940 gfc_add_block_to_block (pblock
, &se
.pre
);
941 to
= gfc_evaluate_now (se
.expr
, pblock
);
943 gfc_init_se (&se
, NULL
);
944 gfc_conv_expr_val (&se
, code
->ext
.iterator
->step
);
945 gfc_add_block_to_block (pblock
, &se
.pre
);
946 step
= gfc_evaluate_now (se
.expr
, pblock
);
948 /* Special case simple loops. */
949 if (integer_onep (step
))
951 else if (tree_int_cst_equal (step
, integer_minus_one_node
))
957 init
= build2_v (MODIFY_EXPR
, dovar
, from
);
958 cond
= build2 (simple
> 0 ? LE_EXPR
: GE_EXPR
, boolean_type_node
,
960 incr
= fold_build2 (PLUS_EXPR
, type
, dovar
, step
);
961 incr
= fold_build2 (MODIFY_EXPR
, type
, dovar
, incr
);
962 if (pblock
!= &block
)
965 gfc_start_block (&block
);
967 gfc_start_block (&body
);
971 /* STEP is not 1 or -1. Use:
972 for (count = 0; count < (to + step - from) / step; count++)
974 dovar = from + count * step;
978 tmp
= fold_build2 (MINUS_EXPR
, type
, step
, from
);
979 tmp
= fold_build2 (PLUS_EXPR
, type
, to
, tmp
);
980 tmp
= fold_build2 (TRUNC_DIV_EXPR
, type
, tmp
, step
);
981 tmp
= gfc_evaluate_now (tmp
, pblock
);
982 count
= gfc_create_var (type
, "count");
983 init
= build2_v (MODIFY_EXPR
, count
, build_int_cst (type
, 0));
984 cond
= build2 (LT_EXPR
, boolean_type_node
, count
, tmp
);
985 incr
= fold_build2 (PLUS_EXPR
, type
, count
, build_int_cst (type
, 1));
986 incr
= fold_build2 (MODIFY_EXPR
, type
, count
, incr
);
988 if (pblock
!= &block
)
991 gfc_start_block (&block
);
993 gfc_start_block (&body
);
995 /* Initialize DOVAR. */
996 tmp
= fold_build2 (MULT_EXPR
, type
, count
, step
);
997 tmp
= build2 (PLUS_EXPR
, type
, from
, tmp
);
998 gfc_add_modify_expr (&body
, dovar
, tmp
);
1003 tmp
= build_omp_clause (OMP_CLAUSE_PRIVATE
);
1004 OMP_CLAUSE_DECL (tmp
) = dovar
;
1005 omp_clauses
= gfc_trans_add_clause (tmp
, omp_clauses
);
1009 tmp
= build_omp_clause (OMP_CLAUSE_PRIVATE
);
1010 OMP_CLAUSE_DECL (tmp
) = count
;
1011 omp_clauses
= gfc_trans_add_clause (tmp
, omp_clauses
);
1014 /* Cycle statement is implemented with a goto. Exit statement must not be
1015 present for this loop. */
1016 cycle_label
= gfc_build_label_decl (NULL_TREE
);
1018 /* Put these labels where they can be found later. We put the
1019 labels in a TREE_LIST node (because TREE_CHAIN is already
1020 used). cycle_label goes in TREE_PURPOSE (backend_decl), exit
1021 label in TREE_VALUE (backend_decl). */
1023 code
->block
->backend_decl
= tree_cons (cycle_label
, NULL
, NULL
);
1025 /* Main loop body. */
1026 tmp
= gfc_trans_omp_code (code
->block
->next
, true);
1027 gfc_add_expr_to_block (&body
, tmp
);
1029 /* Label for cycle statements (if needed). */
1030 if (TREE_USED (cycle_label
))
1032 tmp
= build1_v (LABEL_EXPR
, cycle_label
);
1033 gfc_add_expr_to_block (&body
, tmp
);
1036 /* End of loop body. */
1037 stmt
= make_node (OMP_FOR
);
1039 TREE_TYPE (stmt
) = void_type_node
;
1040 OMP_FOR_BODY (stmt
) = gfc_finish_block (&body
);
1041 OMP_FOR_CLAUSES (stmt
) = omp_clauses
;
1042 OMP_FOR_INIT (stmt
) = init
;
1043 OMP_FOR_COND (stmt
) = cond
;
1044 OMP_FOR_INCR (stmt
) = incr
;
1045 gfc_add_expr_to_block (&block
, stmt
);
1047 return gfc_finish_block (&block
);
1051 gfc_trans_omp_flush (void)
1053 tree decl
= built_in_decls
[BUILT_IN_SYNCHRONIZE
];
1054 return build_function_call_expr (decl
, NULL
);
1058 gfc_trans_omp_master (gfc_code
*code
)
1060 tree stmt
= gfc_trans_code (code
->block
->next
);
1061 if (IS_EMPTY_STMT (stmt
))
1063 return build1_v (OMP_MASTER
, stmt
);
1067 gfc_trans_omp_ordered (gfc_code
*code
)
1069 return build1_v (OMP_ORDERED
, gfc_trans_code (code
->block
->next
));
1073 gfc_trans_omp_parallel (gfc_code
*code
)
1076 tree stmt
, omp_clauses
;
1078 gfc_start_block (&block
);
1079 omp_clauses
= gfc_trans_omp_clauses (&block
, code
->ext
.omp_clauses
,
1081 stmt
= gfc_trans_omp_code (code
->block
->next
, true);
1082 stmt
= build4_v (OMP_PARALLEL
, stmt
, omp_clauses
, NULL
, NULL
);
1083 gfc_add_expr_to_block (&block
, stmt
);
1084 return gfc_finish_block (&block
);
1088 gfc_trans_omp_parallel_do (gfc_code
*code
)
1090 stmtblock_t block
, *pblock
= NULL
;
1091 gfc_omp_clauses parallel_clauses
, do_clauses
;
1092 tree stmt
, omp_clauses
= NULL_TREE
;
1094 gfc_start_block (&block
);
1096 memset (&do_clauses
, 0, sizeof (do_clauses
));
1097 if (code
->ext
.omp_clauses
!= NULL
)
1099 memcpy (¶llel_clauses
, code
->ext
.omp_clauses
,
1100 sizeof (parallel_clauses
));
1101 do_clauses
.sched_kind
= parallel_clauses
.sched_kind
;
1102 do_clauses
.chunk_size
= parallel_clauses
.chunk_size
;
1103 do_clauses
.ordered
= parallel_clauses
.ordered
;
1104 parallel_clauses
.sched_kind
= OMP_SCHED_NONE
;
1105 parallel_clauses
.chunk_size
= NULL
;
1106 parallel_clauses
.ordered
= false;
1107 omp_clauses
= gfc_trans_omp_clauses (&block
, ¶llel_clauses
,
1110 do_clauses
.nowait
= true;
1111 if (!do_clauses
.ordered
&& do_clauses
.sched_kind
!= OMP_SCHED_STATIC
)
1115 stmt
= gfc_trans_omp_do (code
, pblock
, &do_clauses
);
1116 if (TREE_CODE (stmt
) != BIND_EXPR
)
1117 stmt
= build3_v (BIND_EXPR
, NULL
, stmt
, poplevel (1, 0, 0));
1120 stmt
= build4_v (OMP_PARALLEL
, stmt
, omp_clauses
, NULL
, NULL
);
1121 OMP_PARALLEL_COMBINED (stmt
) = 1;
1122 gfc_add_expr_to_block (&block
, stmt
);
1123 return gfc_finish_block (&block
);
1127 gfc_trans_omp_parallel_sections (gfc_code
*code
)
1130 gfc_omp_clauses section_clauses
;
1131 tree stmt
, omp_clauses
;
1133 memset (§ion_clauses
, 0, sizeof (section_clauses
));
1134 section_clauses
.nowait
= true;
1136 gfc_start_block (&block
);
1137 omp_clauses
= gfc_trans_omp_clauses (&block
, code
->ext
.omp_clauses
,
1140 stmt
= gfc_trans_omp_sections (code
, §ion_clauses
);
1141 if (TREE_CODE (stmt
) != BIND_EXPR
)
1142 stmt
= build3_v (BIND_EXPR
, NULL
, stmt
, poplevel (1, 0, 0));
1145 stmt
= build4_v (OMP_PARALLEL
, stmt
, omp_clauses
, NULL
, NULL
);
1146 OMP_PARALLEL_COMBINED (stmt
) = 1;
1147 gfc_add_expr_to_block (&block
, stmt
);
1148 return gfc_finish_block (&block
);
1152 gfc_trans_omp_parallel_workshare (gfc_code
*code
)
1155 gfc_omp_clauses workshare_clauses
;
1156 tree stmt
, omp_clauses
;
1158 memset (&workshare_clauses
, 0, sizeof (workshare_clauses
));
1159 workshare_clauses
.nowait
= true;
1161 gfc_start_block (&block
);
1162 omp_clauses
= gfc_trans_omp_clauses (&block
, code
->ext
.omp_clauses
,
1165 stmt
= gfc_trans_omp_workshare (code
, &workshare_clauses
);
1166 if (TREE_CODE (stmt
) != BIND_EXPR
)
1167 stmt
= build3_v (BIND_EXPR
, NULL
, stmt
, poplevel (1, 0, 0));
1170 stmt
= build4_v (OMP_PARALLEL
, stmt
, omp_clauses
, NULL
, NULL
);
1171 OMP_PARALLEL_COMBINED (stmt
) = 1;
1172 gfc_add_expr_to_block (&block
, stmt
);
1173 return gfc_finish_block (&block
);
1177 gfc_trans_omp_sections (gfc_code
*code
, gfc_omp_clauses
*clauses
)
1179 stmtblock_t block
, body
;
1180 tree omp_clauses
, stmt
;
1181 bool has_lastprivate
= clauses
->lists
[OMP_LIST_LASTPRIVATE
] != NULL
;
1183 gfc_start_block (&block
);
1185 omp_clauses
= gfc_trans_omp_clauses (&block
, clauses
, code
->loc
);
1187 gfc_init_block (&body
);
1188 for (code
= code
->block
; code
; code
= code
->block
)
1190 /* Last section is special because of lastprivate, so even if it
1191 is empty, chain it in. */
1192 stmt
= gfc_trans_omp_code (code
->next
,
1193 has_lastprivate
&& code
->block
== NULL
);
1194 if (! IS_EMPTY_STMT (stmt
))
1196 stmt
= build1_v (OMP_SECTION
, stmt
);
1197 gfc_add_expr_to_block (&body
, stmt
);
1200 stmt
= gfc_finish_block (&body
);
1202 stmt
= build2_v (OMP_SECTIONS
, stmt
, omp_clauses
);
1203 gfc_add_expr_to_block (&block
, stmt
);
1205 return gfc_finish_block (&block
);
1209 gfc_trans_omp_single (gfc_code
*code
, gfc_omp_clauses
*clauses
)
1211 tree omp_clauses
= gfc_trans_omp_clauses (NULL
, clauses
, code
->loc
);
1212 tree stmt
= gfc_trans_omp_code (code
->block
->next
, true);
1213 stmt
= build2_v (OMP_SINGLE
, stmt
, omp_clauses
);
1218 gfc_trans_omp_workshare (gfc_code
*code
, gfc_omp_clauses
*clauses
)
1221 return gfc_trans_omp_single (code
, clauses
);
1225 gfc_trans_omp_directive (gfc_code
*code
)
1229 case EXEC_OMP_ATOMIC
:
1230 return gfc_trans_omp_atomic (code
);
1231 case EXEC_OMP_BARRIER
:
1232 return gfc_trans_omp_barrier ();
1233 case EXEC_OMP_CRITICAL
:
1234 return gfc_trans_omp_critical (code
);
1236 return gfc_trans_omp_do (code
, NULL
, code
->ext
.omp_clauses
);
1237 case EXEC_OMP_FLUSH
:
1238 return gfc_trans_omp_flush ();
1239 case EXEC_OMP_MASTER
:
1240 return gfc_trans_omp_master (code
);
1241 case EXEC_OMP_ORDERED
:
1242 return gfc_trans_omp_ordered (code
);
1243 case EXEC_OMP_PARALLEL
:
1244 return gfc_trans_omp_parallel (code
);
1245 case EXEC_OMP_PARALLEL_DO
:
1246 return gfc_trans_omp_parallel_do (code
);
1247 case EXEC_OMP_PARALLEL_SECTIONS
:
1248 return gfc_trans_omp_parallel_sections (code
);
1249 case EXEC_OMP_PARALLEL_WORKSHARE
:
1250 return gfc_trans_omp_parallel_workshare (code
);
1251 case EXEC_OMP_SECTIONS
:
1252 return gfc_trans_omp_sections (code
, code
->ext
.omp_clauses
);
1253 case EXEC_OMP_SINGLE
:
1254 return gfc_trans_omp_single (code
, code
->ext
.omp_clauses
);
1255 case EXEC_OMP_WORKSHARE
:
1256 return gfc_trans_omp_workshare (code
, code
->ext
.omp_clauses
);