aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-openmp.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@gcc.gnu.org>2016-11-10 12:38:05 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2016-11-10 12:38:05 +0100
commitb4c3a85be96585374bf95c981ba2f602667cf5b7 (patch)
tree3567be9879613f19b407cad1c5c4fdcbd2f5d4bb /gcc/fortran/trans-openmp.c
parent86bc85065359e0f849a12115ee487d6a408a2fe0 (diff)
downloadgcc-b4c3a85be96585374bf95c981ba2f602667cf5b7.zip
gcc-b4c3a85be96585374bf95c981ba2f602667cf5b7.tar.gz
gcc-b4c3a85be96585374bf95c981ba2f602667cf5b7.tar.bz2
omp-low.c (lower_omp_target): Fix up argument to is_reference.
gcc/ * omp-low.c (lower_omp_target): Fix up argument to is_reference. (expand_omp_ordered_sink): Handle TREE_PURPOSE of deps being TRUNC_DIV_EXPR. * gimplify.c (gimplify_scan_omp_clauses): Likewise. Set ctx->target_map_scalars_firstprivate on OMP_TARGET even for Fortran. Remove omp_no_lastprivate callers. Propagate lastprivate on combined teams distribute parallel for simd even to distribute and teams construct. For OMP_CLAUSE_DEPEND add missing break at the end of OMP_CLAUSE_DEPEND_SINK case. (omp_notice_variable): Use lang_hooks.decls.omp_scalar_p. (omp_no_lastprivate): Removed. (gimplify_adjust_omp_clauses): Remove omp_no_lastprivate callers. (gimplify_omp_for): Likewise. (computable_teams_clause): Fail for automatic vars from current function not yet seen in bind expr. * langhooks.c (lhd_omp_scalar_p): New function. * langhooks.h (struct lang_hooks_for_decls): Add omp_scalar_p. * varpool.c (varpool_node::get_create): Set node->offloading even for DECL_EXTERNAL decls. * langhooks-def.h (lhd_omp_scalar_p): New prototype. (LANG_HOOKS_OMP_SCALAR_P): Define. (LANG_HOOKS_DECLS): Use it. gcc/fortran/ * openmp.c (gfc_free_omp_clauses): Free critical_name, grainsize, hint, num_tasks, priority and if_exprs. (gfc_match_omp_to_link, gfc_match_omp_depend_sink): New functions. (enum omp_mask1, enum omp_mask2): New enums. Change all OMP_CLAUSE_* defines into enum values, and change their values from ((uint64_t) 1 << bit) to just bit. (omp_mask, omp_inv_mask): New classes. Add ctors and operators. (gfc_match_omp_clauses): Change mask argument from uint64_t to const omp_mask. Assert OMP_MASK1_LAST and OMP_MASK2_LAST are at most 64. Move delete clause handling to where it alphabetically belongs. Parse defaultmap, grainsize, hint, is_device_ptr, nogroup, nowait, num_tasks, priority, simd, threads and use_device_ptr clauses. Parse if clause modifier. Parse map clause always modifier, and release and delete kinds. Parse ordered clause with argument. Parse schedule clause modifiers. Differentiate device clause parsing based on openacc flag. Guard link clause parsing with openacc flag. Add support for parsing linear clause modifiers. Parse depend(source) and depend(sink: ...). Use gfc_match_omp_to_link for to and link clauses in declare target construct. (match_acc): Change mask type from uint64_t to const omp_mask. (OMP_SINGLE_CLAUSES, OMP_ORDERED_CLAUSES, OMP_DECLARE_TARGET_CLAUSES, OMP_TASKLOOP_CLAUSES, OMP_TARGET_ENTER_DATA_CLAUSES, OMP_TARGET_EXIT_DATA_CLAUSES): Define. (OACC_PARALLEL_CLAUSES, OACC_KERNELS_CLAUSES, OACC_DATA_CLAUSES, OACC_LOOP_CLAUSES, OACC_HOST_DATA_CLAUSES, OACC_DECLARE_CLAUSES, OACC_ENTER_DATA_CLAUSES, OACC_EXIT_DATA_CLAUSES, OACC_WAIT_CLAUSES, OACC_ROUTINE_CLAUSES, OMP_PARALLEL_CLAUSES, OMP_DECLARE_SIMD_CLAUSES, OMP_SECTIONS_CLAUSES, OMP_TEAMS_CLAUSES, OMP_DISTRIBUTE_CLAUSES): Replace first or only OMP_CLAUSE_* value in bitset with omp_mask (OMP_CLAUSE_*). (OMP_DO_CLAUSES): Likewise. Add OMP_CLAUSE_LINEAR. (OMP_SIMD_CLAUSES): Replace first or only OMP_CLAUSE_* value in bitset with omp_mask (OMP_CLAUSE_*). Add OMP_CLAUSE_SIMDLEN. (OACC_UPDATE_CLAUSES): Replace first or only OMP_CLAUSE_* value in bitset with omp_mask (OMP_CLAUSE_*). Replace OMP_CLAUSE_OACC_DEVICE with OMP_CLAUSE_DEVICE. (OMP_TASK_CLAUSES): Replace first or only OMP_CLAUSE_* value in bitset with omp_mask (OMP_CLAUSE_*). Add OMP_CLAUSE_PRIORITY. (OMP_TARGET_CLAUSES): Replace first or only OMP_CLAUSE_* value in bitset with omp_mask (OMP_CLAUSE_*). Add OMP_CLAUSE_DEPEND, OMP_CLAUSE_NOWAIT, OMP_CLAUSE_PRIVATE, OMP_CLAUSE_FIRSTPRIVATE, OMP_CLAUSE_DEFAULTMAP and OMP_CLAUSE_IS_DEVICE_PTR. (OMP_TARGET_DATA_CLAUSES): Replace first or only OMP_CLAUSE_* value in bitset with omp_mask (OMP_CLAUSE_*). Add OMP_CLAUSE_USE_DEVICE_PTR. (OMP_TARGET_UPDATE_CLAUSES): Replace first or only OMP_CLAUSE_* value in bitset with omp_mask (OMP_CLAUSE_*). Add OMP_CLAUSE_DEPEND and OMP_CLAUSE_NOWAIT. (match_omp): Change mask argument from unsigned int to const omp_mask. (gfc_match_omp_critical): Parse optional clauses and use omp_clauses union member instead of omp_name. (gfc_match_omp_end_critical): New function. (gfc_match_omp_distribute_parallel_do): Remove ordered and linear clauses from the mask. (gfc_match_omp_distribute_parallel_do_simd): Use & ~(omp_mask (OMP_CLAUSE_*)) instead of & ~OMP_CLAUSE_*. (gfc_match_omp_target_teams_distribute_parallel_do_simd): Likewise. (gfc_match_omp_teams_distribute_parallel_do_simd): Likewise. (gfc_match_omp_do_simd): Likewise. Don't remove ordered clause from the mask. (gfc_match_omp_parallel_do_simd): Likewise. (gfc_match_omp_target_teams_distribute_parallel_do): Likewise. (gfc_match_omp_teams_distribute_parallel_do): Likewise. (gfc_match_omp_declare_simd): If not using the form with (proc-name), require space before first clause. Make (proc-name) optional. If not present, set proc_name to NULL. (gfc_match_omp_declare_target): Rewritten for OpenMP 4.5. (gfc_match_omp_single): Use OMP_SINGLE_CLAUSES. (gfc_match_omp_task, gfc_match_omp_taskwait, gfc_match_omp_taskyield): Move around to where they belong alphabetically. (gfc_match_omp_target_enter_data, gfc_match_omp_target_exit_data, gfc_match_omp_target_parallel, gfc_match_omp_target_parallel_do, gfc_match_omp_target_parallel_do_simd, gfc_match_omp_target_simd, gfc_match_omp_taskloop, gfc_match_omp_taskloop_simd): New functions. (gfc_match_omp_ordered): Parse clauses. (gfc_match_omp_ordered_depend): New function. (gfc_match_omp_cancel, gfc_match_omp_end_single): Use omp_mask (OMP_CLAUSE_*) instead of OMP_CLAUSE_*. (resolve_oacc_scalar_int_expr): Renamed to ... (resolve_scalar_int_expr): ... this. Fix up formatting. (resolve_oacc_positive_int_expr): Renamed to ... (resolve_positive_int_expr): ... this. Fix up formatting. (resolve_nonnegative_int_expr): New function. (resolve_omp_clauses): Adjust callers, use the above functions even for OpenMP clauses, add handling of new OpenMP 4.5 clauses. Require orderedc >= collapse if specified. Handle depend(sink:) and depend(source) restrictions. Disallow linear clause when orderedc is non-zero. Diagnose linear clause modifiers when not in declare simd. Only check for integer type if ref modifier is not used. Remove diagnostics for required VALUE attribute. Diagnose VALUE attribute with ref or uval modifiers. Allow non-constant linear-step, if it is a dummy argument alone and is mentioned in uniform clause. Diagnose map kinds not allowed for various constructs. Diagnose target {enter ,exit ,}data without any map clauses. Add dummy OMP_LIST_IS_DEVICE_PTR and OMP_LIST_USE_DEVICE_PTR cases. (gfc_resolve_omp_do_blocks): Set omp_current_do_collapse to orderedc if non-zero. (gfc_resolve_omp_parallel_blocks): Handle new OpenMP 4.5 constructs, replace underscores with spaces in a few construct names. (resolve_omp_do): Set collapse to orderedc if non-zero. Handle new OpenMP 4.5 constructs. (resolve_oacc_loop_blocks): Call resolve_positive_int_expr instead of resolve_oacc_positive_int_expr. (gfc_resolve_omp_directive): Handle new OpenMP 4.5 constructs. (gfc_resolve_omp_declare_simd): Allow ods->proc_name to be NULL. * trans-openmp.c (gfc_omp_scalar_p): New function. (doacross_steps): New variable. (gfc_trans_omp_clauses): Handle new OpenMP 4.5 clauses and new clause modifiers. (gfc_trans_omp_critical): Adjust EXEC_OMP_CRITICAL handling. (gfc_trans_omp_do): Handle doacross loops. Clear sched_simd flag. Handle EXEC_OMP_TASKLOOP. (gfc_trans_omp_ordered): Translate omp clauses, allow NULL code->block. (GFC_OMP_SPLIT_TASKLOOP, GFC_OMP_MASK_TASKLOOP): New enum constants. (gfc_split_omp_clauses): Copy orderedc together with ordered. Change firstprivate and lastprivate handling for OpenMP 4.5. Handle EXEC_OMP_TARGET_SIMD, EXEC_OMP_TARGET_PARALLEL{,_DO,_DO_SIMD} and EXEC_OMP_TASKLOOP{,_SIMD}. Add handling for new OpenMP 4.5 clauses and clause modifiers and handle if clause without/with modifiers. (gfc_trans_omp_teams): Add omp_clauses argument, add it to other teams clauses. Don't wrap into OMP_TEAMS if -fopenmp-simd. (gfc_trans_omp_target): For -fopenmp, translate num_teams and thread_limit clauses on combined target teams early and pass to gfc_trans_omp_teams. Set OMP_TARGET_COMBINED if needed. Handle EXEC_OMP_TARGET_PARALLEL{,_DO,_DO_SIMD} and EXEC_OMP_TARGET_SIMD. (gfc_trans_omp_taskloop, gfc_trans_omp_target_enter_data, gfc_trans_omp_target_exit_data): New functions. (gfc_trans_omp_directive): Handle EXEC_OMP_TARGET_{ENTER,EXIT}_DATA EXEC_OMP_TASKLOOP{,_SIMD}, EXEC_OMP_TARGET_PARALLEL{,_DO,_DO_SIMD} and EXEC_OMP_TARGET_SIMD. Adjust gfc_trans_omp_teams caller. * symbol.c (check_conflict): Handle omp_declare_target_link. (gfc_add_omp_declare_target_link): New function. (gfc_copy_attr): Copy omp_declare_target_link. * dump-parse-tree.c (show_omp_namelist): Handle OMP_DEPEND_SINK_FIRST depend_op. Print linear clause modifiers. (show_omp_clauses): Adjust for OpenMP 4.5 clause changes. (show_omp_node): Print clauses for EXEC_OMP_ORDERED. Allow NULL c->block for EXEC_OMP_ORDERED. Formatting fixes. Adjust handling of EXEC_OMP_CRITICAL, handle new OpenMP 4.5 constructs and some forgotten OpenMP 4.0 constructs. (show_code_node): Handle new OpenMP 4.5 constructs and some forgotten OpenMP 4.0 constructs. * gfortran.h (symbol_attribute): Add omp_declare_target_link bitfield. (struct gfc_omp_namelist): Add u.common and u.linear_op fields. (struct gfc_common_head): Change omp_declare_target into bitfield. Add omp_declare_target_link bitfield. (gfc_add_omp_declare_target_link): New prototype. (enum gfc_statement): Add ST_OMP_TARGET_PARALLEL, ST_OMP_END_TARGET_PARALLEL, ST_OMP_TARGET_PARALLEL_DO, ST_OMP_END_TARGET_PARALLEL_DO, ST_OMP_TARGET_PARALLEL_DO_SIMD, ST_OMP_END_TARGET_PARALLEL_DO_SIMD, ST_OMP_TARGET_ENTER_DATA, ST_OMP_TARGET_EXIT_DATA, ST_OMP_TARGET_SIMD, ST_OMP_END_TARGET_SIMD, ST_OMP_TASKLOOP, ST_OMP_END_TASKLOOP, ST_OMP_TASKLOOP_SIMD, ST_OMP_END_TASKLOOP_SIMD and ST_OMP_ORDERED_DEPEND. (enum gfc_omp_depend_op): Add OMP_DEPEND_SINK_FIRST and OMP_DEPEND_SINK. (enum gfc_omp_linear_op): New. (struct gfc_omp_clauses): Add critical_name, depend_source, orderedc, defaultmap, nogroup, sched_simd, sched_monotonic, sched_nonmonotonic, simd, threads, grainsize, hint, num_tasks, priority and if_exprs fields. (enum gfc_exec_op): Add EXEC_OMP_END_CRITICAL, EXEC_OMP_TARGET_ENTER_DATA, EXEC_OMP_TARGET_EXIT_DATA, EXEC_OMP_TARGET_PARALLEL, EXEC_OMP_TARGET_PARALLEL_DO, EXEC_OMP_TARGET_PARALLEL_DO_SIMD, EXEC_OMP_TARGET_SIMD, EXEC_OMP_TASKLOOP, EXEC_OMP_TASKLOOP_SIMD. (enum gfc_omp_map_op): Add OMP_MAP_RELEASE, OMP_MAP_ALWAYS_TO, OMP_MAP_ALWAYS_FROM and OMP_MAP_ALWAYS_TOFROM. (OMP_LIST_IS_DEVICE_PTR, OMP_LIST_USE_DEVICE_PTR): New. (enum gfc_omp_if_kind): New. * module.c (enum ab_attribute): Add AB_OMP_DECLARE_TARGET_LINK. (attr_bits): Add AB_OMP_DECLARE_TARGET_LINK entry. (mio_symbol_attribute): Save and restore omp_declare_target_link bit. * trans.h (gfc_omp_scalar_p): New prototype. * frontend-passes.c (gfc_code_walker): Handle new OpenMP 4.5 expressions. * trans.c (trans_code): Handle new OpenMP 4.5 constructs. * resolve.c (gfc_resolve_blocks): Likewise. (gfc_resolve_code): Likewise. * f95-lang.c (LANG_HOOKS_OMP_SCALAR_P): Redefine to gfc_omp_scalar_p. (gfc_attribute_table): Add "omp declare target link". * st.c (gfc_free_statement): Handle EXEC_OMP_END_CRITICAL like EXEC_OMP_CRITICAL before, free clauses for EXEC_OMP_CRITICAL and new OpenMP 4.5 constructs. Free omp clauses even for EXEC_OMP_ORDERED. * match.c (match_exit_cycle): Rename collapse variable to count, set it to orderedc if non-zero, instead of collapse. * trans-decl.c (add_attributes_to_decl): Add "omp declare target link" instead of "omp declare target" for omp_declare_target_link. * trans-common.c (build_common_decl): Likewise. * match.h (gfc_match_omp_target_enter_data, gfc_match_omp_target_exit_data, gfc_match_omp_target_parallel, gfc_match_omp_target_parallel_do, gfc_match_omp_target_parallel_do_simd, gfc_match_omp_target_simd, gfc_match_omp_taskloop, gfc_match_omp_taskloop_simd, gfc_match_omp_end_critical, gfc_match_omp_ordered_depend): New prototypes. * parse.c (decode_omp_directive): Use gfc_match_omp_end_critical instead of gfc_match_omp_critical for !$omp end critical. Handle new OpenMP 4.5 constructs. If ordered directive has depend clause as the first of the clauses, use gfc_match_omp_ordered_depend and ST_OMP_ORDERED_DEPEND instead of gfc_match_omp_ordered and ST_OMP_ORDERED. (case_executable): Add ST_OMP_TARGET_ENTER_DATA, ST_OMP_TARGET_EXIT_DATA and ST_OMP_ORDERED_DEPEND cases. (case_exec_markers): Add ST_OMP_TARGET_PARALLEL, ST_OMP_TARGET_PARALLEL_DO, ST_OMP_TARGET_PARALLEL_DO_SIMD, ST_OMP_TARGET_SIMD, ST_OMP_TASKLOOP and ST_OMP_TASKLOOP_SIMD cases. (gfc_ascii_statement): Handle new OpenMP 4.5 constructs. (parse_omp_do): Handle ST_OMP_TARGET_PARALLEL_DO, ST_OMP_TARGET_PARALLEL_DO_SIMD, ST_OMP_TASKLOOP and ST_OMP_TASKLOOP_SIMD. (parse_omp_structured_block): Handle EXEC_OMP_END_CRITICAL instead of EXEC_OMP_CRITICAL, adjust for EXEC_OMP_CRITICAL having omp clauses now. (parse_executable): Handle ST_OMP_TARGET_PARALLEL, ST_OMP_TARGET_PARALLEL_DO, ST_OMP_TARGET_PARALLEL_DO_SIMD, ST_OMP_TASKLOOP and ST_OMP_TASKLOOP_SIMD. gcc/testsuite/ * gfortran.dg/gomp/pr77516.f90: Add dg-warning. * gfortran.dg/gomp/target1.f90: Remove ordered clause where it is no longer allowed and corresponding ordered construct. * gfortran.dg/gomp/linear-1.f90: New test. * gfortran.dg/gomp/declare-simd-2.f90: New test. * gfortran.dg/gomp/declare-target-1.f90: New test. * gfortran.dg/gomp/declare-target-2.f90: New test. libgomp/ * testsuite/libgomp.fortran/examples-4/declare_target-1.f90 (fib_wrapper): Add map(from: x) clause. * testsuite/libgomp.fortran/examples-4/declare_target-2.f90 (e_53_2): Likewise. * testsuite/libgomp.fortran/examples-4/declare_target-4.f90 (accum): Add map(tmp) clause. * testsuite/libgomp.fortran/examples-4/declare_target-5.f90 (accum): Add map(tofrom: tmp) clause. * testsuite/libgomp.fortran/examples-4/target_data-3.f90 (gramSchmidt): Likewise. * testsuite/libgomp.fortran/examples-4/teams-2.f90 (dotprod): Add map(tofrom: sum) clause. * testsuite/libgomp.fortran/nestedfn5.f90 (foo): Add twice map (alloc: a, l) clause. Add defaultmap(tofrom: scalar) clause. * testsuite/libgomp.fortran/pr66199-2.f90: Adjust for linear clause only allowed on the loop iterator. * testsuite/libgomp.fortran/target4.f90 (foo): Add map(t) clause. * testsuite/libgomp.fortran/taskloop2.f90: New test. * testsuite/libgomp.fortran/taskloop4.f90: New test. * testsuite/libgomp.fortran/doacross1.f90: New test. * testsuite/libgomp.fortran/doacross3.f90: New test. * testsuite/libgomp.fortran/taskloop1.f90: New test. * testsuite/libgomp.fortran/taskloop3.f90: New test. * testsuite/libgomp.fortran/doacross2.f90: New test. * testsuite/libgomp.c/doacross-1.c (main): Add missing #pragma omp atomic read. * testsuite/libgomp.c/doacross-2.c (main): Likewise. * testsuite/libgomp.c/doacross-3.c (main): Likewise. From-SVN: r242037
Diffstat (limited to 'gcc/fortran/trans-openmp.c')
-rw-r--r--gcc/fortran/trans-openmp.c678
1 files changed, 624 insertions, 54 deletions
diff --git a/gcc/fortran/trans-openmp.c b/gcc/fortran/trans-openmp.c
index febff25..59fd6b3 100644
--- a/gcc/fortran/trans-openmp.c
+++ b/gcc/fortran/trans-openmp.c
@@ -1140,6 +1140,34 @@ gfc_omp_finish_clause (tree c, gimple_seq *pre_p)
}
+/* Return true if DECL is a scalar variable (for the purpose of
+ implicit firstprivatization). */
+
+bool
+gfc_omp_scalar_p (tree decl)
+{
+ tree type = TREE_TYPE (decl);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ if (GFC_DECL_GET_SCALAR_ALLOCATABLE (decl)
+ || GFC_DECL_GET_SCALAR_POINTER (decl))
+ type = TREE_TYPE (type);
+ if (GFC_ARRAY_TYPE_P (type)
+ || GFC_CLASS_TYPE_P (type))
+ return false;
+ }
+ if (TYPE_STRING_FLAG (type))
+ return false;
+ if (INTEGRAL_TYPE_P (type)
+ || SCALAR_FLOAT_TYPE_P (type)
+ || COMPLEX_FLOAT_TYPE_P (type))
+ return true;
+ return false;
+}
+
+
/* Return true if DECL's DECL_VALUE_EXPR (if any) should be
disregarded in OpenMP construct, because it is going to be
remapped during OpenMP lowering. SHARED is true if DECL
@@ -1727,12 +1755,14 @@ gfc_convert_expr_to_tree (stmtblock_t *block, gfc_expr *expr)
return result;
}
+static vec<tree, va_heap, vl_embed> *doacross_steps;
+
static tree
gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
locus where, bool declare_simd = false)
{
tree omp_clauses = NULL_TREE, chunk_size, c;
- int list;
+ int list, ifc;
enum omp_clause_code clause_code;
gfc_se se;
@@ -1775,8 +1805,12 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
clause_code = OMP_CLAUSE_UNIFORM;
goto add_clause;
case OMP_LIST_USE_DEVICE:
+ case OMP_LIST_USE_DEVICE_PTR:
clause_code = OMP_CLAUSE_USE_DEVICE_PTR;
goto add_clause;
+ case OMP_LIST_IS_DEVICE_PTR:
+ clause_code = OMP_CLAUSE_IS_DEVICE_PTR;
+ goto add_clause;
add_clause:
omp_clauses
@@ -1797,7 +1831,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
{
tree alignment_var;
- if (block == NULL)
+ if (declare_simd)
alignment_var = gfc_conv_constant_to_tree (n->expr);
else
{
@@ -1817,6 +1851,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
{
gfc_expr *last_step_expr = NULL;
tree last_step = NULL_TREE;
+ bool last_step_parm = false;
for (; n != NULL; n = n->next)
{
@@ -1824,6 +1859,7 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
{
last_step_expr = n->expr;
last_step = NULL_TREE;
+ last_step_parm = false;
}
if (n->sym->attr.referenced || declare_simd)
{
@@ -1833,12 +1869,28 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
tree node = build_omp_clause (input_location,
OMP_CLAUSE_LINEAR);
OMP_CLAUSE_DECL (node) = t;
+ omp_clause_linear_kind kind;
+ switch (n->u.linear_op)
+ {
+ case OMP_LINEAR_DEFAULT:
+ kind = OMP_CLAUSE_LINEAR_DEFAULT;
+ break;
+ case OMP_LINEAR_REF:
+ kind = OMP_CLAUSE_LINEAR_REF;
+ break;
+ case OMP_LINEAR_VAL:
+ kind = OMP_CLAUSE_LINEAR_VAL;
+ break;
+ case OMP_LINEAR_UVAL:
+ kind = OMP_CLAUSE_LINEAR_UVAL;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ OMP_CLAUSE_LINEAR_KIND (node) = kind;
if (last_step_expr && last_step == NULL_TREE)
{
- if (block == NULL)
- last_step
- = gfc_conv_constant_to_tree (last_step_expr);
- else
+ if (!declare_simd)
{
gfc_init_se (&se, NULL);
gfc_conv_expr (&se, last_step_expr);
@@ -1846,10 +1898,27 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
last_step = gfc_evaluate_now (se.expr, block);
gfc_add_block_to_block (block, &se.post);
}
+ else if (last_step_expr->expr_type == EXPR_VARIABLE)
+ {
+ gfc_symbol *s = last_step_expr->symtree->n.sym;
+ last_step = gfc_trans_omp_variable (s, true);
+ last_step_parm = true;
+ }
+ else
+ last_step
+ = gfc_conv_constant_to_tree (last_step_expr);
+ }
+ if (last_step_parm)
+ {
+ OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (node) = 1;
+ OMP_CLAUSE_LINEAR_STEP (node) = last_step;
+ }
+ else
+ {
+ tree type = gfc_typenode_for_spec (&n->sym->ts);
+ OMP_CLAUSE_LINEAR_STEP (node)
+ = fold_convert (type, last_step);
}
- OMP_CLAUSE_LINEAR_STEP (node)
- = fold_convert (gfc_typenode_for_spec (&n->sym->ts),
- last_step);
if (n->sym->attr.dimension || n->sym->attr.allocatable)
OMP_CLAUSE_LINEAR_ARRAY (node) = 1;
omp_clauses = gfc_trans_add_clause (node, omp_clauses);
@@ -1861,6 +1930,57 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
case OMP_LIST_DEPEND:
for (; n != NULL; n = n->next)
{
+ if (n->u.depend_op == OMP_DEPEND_SINK_FIRST)
+ {
+ tree vec = NULL_TREE;
+ unsigned int i;
+ for (i = 0; ; i++)
+ {
+ tree addend = integer_zero_node, t;
+ bool neg = false;
+ if (n->expr)
+ {
+ addend = gfc_conv_constant_to_tree (n->expr);
+ if (TREE_CODE (addend) == INTEGER_CST
+ && tree_int_cst_sgn (addend) == -1)
+ {
+ neg = true;
+ addend = const_unop (NEGATE_EXPR,
+ TREE_TYPE (addend), addend);
+ }
+ }
+ t = gfc_trans_omp_variable (n->sym, false);
+ if (t != error_mark_node)
+ {
+ if (i < vec_safe_length (doacross_steps)
+ && !integer_zerop (addend)
+ && (*doacross_steps)[i])
+ {
+ tree step = (*doacross_steps)[i];
+ addend = fold_convert (TREE_TYPE (step), addend);
+ addend = build2 (TRUNC_DIV_EXPR,
+ TREE_TYPE (step), addend, step);
+ }
+ vec = tree_cons (addend, t, vec);
+ if (neg)
+ OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
+ }
+ if (n->next == NULL
+ || n->next->u.depend_op != OMP_DEPEND_SINK)
+ break;
+ n = n->next;
+ }
+ if (vec == NULL_TREE)
+ continue;
+
+ tree node = build_omp_clause (input_location,
+ OMP_CLAUSE_DEPEND);
+ OMP_CLAUSE_DEPEND_KIND (node) = OMP_CLAUSE_DEPEND_SINK;
+ OMP_CLAUSE_DECL (node) = nreverse (vec);
+ omp_clauses = gfc_trans_add_clause (node, omp_clauses);
+ continue;
+ }
+
if (!n->sym->attr.referenced)
continue;
@@ -2120,6 +2240,18 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
case OMP_MAP_TOFROM:
OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_TOFROM);
break;
+ case OMP_MAP_ALWAYS_TO:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TO);
+ break;
+ case OMP_MAP_ALWAYS_FROM:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_FROM);
+ break;
+ case OMP_MAP_ALWAYS_TOFROM:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_ALWAYS_TOFROM);
+ break;
+ case OMP_MAP_RELEASE:
+ OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_RELEASE);
+ break;
case OMP_MAP_DELETE:
OMP_CLAUSE_SET_MAP_KIND (node, GOMP_MAP_DELETE);
break;
@@ -2260,6 +2392,50 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
OMP_CLAUSE_IF_EXPR (c) = if_var;
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ for (ifc = 0; ifc < OMP_IF_LAST; ifc++)
+ if (clauses->if_exprs[ifc])
+ {
+ tree if_var;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->if_exprs[ifc]);
+ gfc_add_block_to_block (block, &se.pre);
+ if_var = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_IF);
+ switch (ifc)
+ {
+ case OMP_IF_PARALLEL:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_PARALLEL;
+ break;
+ case OMP_IF_TASK:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASK;
+ break;
+ case OMP_IF_TASKLOOP:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_TASKLOOP;
+ break;
+ case OMP_IF_TARGET:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET;
+ break;
+ case OMP_IF_TARGET_DATA:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_DATA;
+ break;
+ case OMP_IF_TARGET_UPDATE:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_UPDATE;
+ break;
+ case OMP_IF_TARGET_ENTER_DATA:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_ENTER_DATA;
+ break;
+ case OMP_IF_TARGET_EXIT_DATA:
+ OMP_CLAUSE_IF_MODIFIER (c) = OMP_TARGET_EXIT_DATA;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ OMP_CLAUSE_IF_EXPR (c) = if_var;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
if (clauses->final_expr)
{
@@ -2325,6 +2501,16 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
default:
gcc_unreachable ();
}
+ if (clauses->sched_monotonic)
+ OMP_CLAUSE_SCHEDULE_KIND (c)
+ = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
+ | OMP_CLAUSE_SCHEDULE_MONOTONIC);
+ else if (clauses->sched_nonmonotonic)
+ OMP_CLAUSE_SCHEDULE_KIND (c)
+ = (omp_clause_schedule_kind) (OMP_CLAUSE_SCHEDULE_KIND (c)
+ | OMP_CLAUSE_SCHEDULE_NONMONOTONIC);
+ if (clauses->sched_simd)
+ OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
@@ -2360,7 +2546,9 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
if (clauses->ordered)
{
c = build_omp_clause (where.lb->location, OMP_CLAUSE_ORDERED);
- OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE;
+ OMP_CLAUSE_ORDERED_EXPR (c)
+ = clauses->orderedc ? build_int_cst (integer_type_node,
+ clauses->orderedc) : NULL_TREE;
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
@@ -2455,10 +2643,27 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
if (clauses->simdlen_expr)
{
- c = build_omp_clause (where.lb->location, OMP_CLAUSE_SIMDLEN);
- OMP_CLAUSE_SIMDLEN_EXPR (c)
- = gfc_conv_constant_to_tree (clauses->simdlen_expr);
- omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ if (declare_simd)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_SIMDLEN);
+ OMP_CLAUSE_SIMDLEN_EXPR (c)
+ = gfc_conv_constant_to_tree (clauses->simdlen_expr);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+ else
+ {
+ tree simdlen_var;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->simdlen_expr);
+ gfc_add_block_to_block (block, &se.pre);
+ simdlen_var = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_SIMDLEN);
+ OMP_CLAUSE_SIMDLEN_EXPR (c) = simdlen_var;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
}
if (clauses->num_teams)
@@ -2523,6 +2728,93 @@ gfc_trans_omp_clauses (stmtblock_t *block, gfc_omp_clauses *clauses,
omp_clauses = gfc_trans_add_clause (c, omp_clauses);
}
+ if (clauses->grainsize)
+ {
+ tree grainsize;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->grainsize);
+ gfc_add_block_to_block (block, &se.pre);
+ grainsize = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_GRAINSIZE);
+ OMP_CLAUSE_GRAINSIZE_EXPR (c) = grainsize;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ if (clauses->num_tasks)
+ {
+ tree num_tasks;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->num_tasks);
+ gfc_add_block_to_block (block, &se.pre);
+ num_tasks = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_NUM_TASKS);
+ OMP_CLAUSE_NUM_TASKS_EXPR (c) = num_tasks;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ if (clauses->priority)
+ {
+ tree priority;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->priority);
+ gfc_add_block_to_block (block, &se.pre);
+ priority = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_PRIORITY);
+ OMP_CLAUSE_PRIORITY_EXPR (c) = priority;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ if (clauses->hint)
+ {
+ tree hint;
+
+ gfc_init_se (&se, NULL);
+ gfc_conv_expr (&se, clauses->hint);
+ gfc_add_block_to_block (block, &se.pre);
+ hint = gfc_evaluate_now (se.expr, block);
+ gfc_add_block_to_block (block, &se.post);
+
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_HINT);
+ OMP_CLAUSE_HINT_EXPR (c) = hint;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
+ if (clauses->simd)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_SIMD);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+ if (clauses->threads)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_THREADS);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+ if (clauses->nogroup)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_NOGROUP);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+ if (clauses->defaultmap)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_DEFAULTMAP);
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+ if (clauses->depend_source)
+ {
+ c = build_omp_clause (where.lb->location, OMP_CLAUSE_DEPEND);
+ OMP_CLAUSE_DEPEND_KIND (c) = OMP_CLAUSE_DEPEND_SOURCE;
+ omp_clauses = gfc_trans_add_clause (c, omp_clauses);
+ }
+
if (clauses->async)
{
c = build_omp_clause (where.lb->location, OMP_CLAUSE_ASYNC);
@@ -3135,8 +3427,8 @@ static tree
gfc_trans_omp_critical (gfc_code *code)
{
tree name = NULL_TREE, stmt;
- if (code->ext.omp_name != NULL)
- name = get_identifier (code->ext.omp_name);
+ if (code->ext.omp_clauses != NULL)
+ name = get_identifier (code->ext.omp_clauses->critical_name);
stmt = gfc_trans_code (code->block->next);
return build3_loc (input_location, OMP_CRITICAL, void_type_node, stmt,
NULL_TREE, name);
@@ -3153,7 +3445,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
gfc_omp_clauses *do_clauses, tree par_clauses)
{
gfc_se se;
- tree dovar, stmt, from, to, step, type, init, cond, incr;
+ tree dovar, stmt, from, to, step, type, init, cond, incr, orig_decls;
tree count = NULL_TREE, cycle_label, tmp, omp_clauses;
stmtblock_t block;
stmtblock_t body;
@@ -3162,7 +3454,11 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
vec<dovar_init> inits = vNULL;
dovar_init *di;
unsigned ix;
+ vec<tree, va_heap, vl_embed> *saved_doacross_steps = doacross_steps;
+ doacross_steps = NULL;
+ if (clauses->orderedc)
+ collapse = clauses->orderedc;
if (collapse <= 0)
collapse = 1;
@@ -3172,6 +3468,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
init = make_tree_vec (collapse);
cond = make_tree_vec (collapse);
incr = make_tree_vec (collapse);
+ orig_decls = clauses->orderedc ? make_tree_vec (collapse) : NULL_TREE;
if (pblock == NULL)
{
@@ -3179,6 +3476,11 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
pblock = &block;
}
+ /* simd schedule modifier is only useful for composite do simd and other
+ constructs including that, where gfc_trans_omp_do is only called
+ on the simd construct and DO's clauses are translated elsewhere. */
+ do_clauses->sched_simd = false;
+
omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc);
for (i = 0; i < collapse; i++)
@@ -3291,7 +3593,15 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
tmp = fold_build2_loc (input_location, PLUS_EXPR, type, from, tmp);
dovar_init e = {dovar, tmp};
inits.safe_push (e);
+ if (clauses->orderedc)
+ {
+ if (doacross_steps == NULL)
+ vec_safe_grow_cleared (doacross_steps, clauses->orderedc);
+ (*doacross_steps)[i] = step;
+ }
}
+ if (orig_decls)
+ TREE_VEC_ELT (orig_decls, i) = dovar_decl;
if (dovar_found == 2
&& op == EXEC_OMP_SIMD
@@ -3338,9 +3648,24 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar
will have the value on entry of the last loop, rather
than value after iterator increment. */
- tmp = gfc_evaluate_now (step, pblock);
- tmp = fold_build2_loc (input_location, PLUS_EXPR, type, dovar,
- tmp);
+ if (clauses->orderedc)
+ {
+ if (clauses->collapse <= 1 || i >= clauses->collapse)
+ tmp = count;
+ else
+ tmp = fold_build2_loc (input_location, PLUS_EXPR,
+ type, count, build_one_cst (type));
+ tmp = fold_build2_loc (input_location, MULT_EXPR, type,
+ tmp, step);
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
+ from, tmp);
+ }
+ else
+ {
+ tmp = gfc_evaluate_now (step, pblock);
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, type,
+ dovar, tmp);
+ }
tmp = fold_build2_loc (input_location, MODIFY_EXPR, type,
dovar, tmp);
for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c))
@@ -3434,6 +3759,7 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
case EXEC_OMP_SIMD: stmt = make_node (OMP_SIMD); break;
case EXEC_OMP_DO: stmt = make_node (OMP_FOR); break;
case EXEC_OMP_DISTRIBUTE: stmt = make_node (OMP_DISTRIBUTE); break;
+ case EXEC_OMP_TASKLOOP: stmt = make_node (OMP_TASKLOOP); break;
case EXEC_OACC_LOOP: stmt = make_node (OACC_LOOP); break;
default: gcc_unreachable ();
}
@@ -3444,8 +3770,13 @@ gfc_trans_omp_do (gfc_code *code, gfc_exec_op op, stmtblock_t *pblock,
OMP_FOR_INIT (stmt) = init;
OMP_FOR_COND (stmt) = cond;
OMP_FOR_INCR (stmt) = incr;
+ if (orig_decls)
+ OMP_FOR_ORIG_DECLS (stmt) = orig_decls;
gfc_add_expr_to_block (&block, stmt);
+ vec_free (doacross_steps);
+ doacross_steps = saved_doacross_steps;
+
return gfc_finish_block (&block);
}
@@ -3547,8 +3878,11 @@ gfc_trans_omp_master (gfc_code *code)
static tree
gfc_trans_omp_ordered (gfc_code *code)
{
+ tree omp_clauses = gfc_trans_omp_clauses (NULL, code->ext.omp_clauses,
+ code->loc);
return build2_loc (input_location, OMP_ORDERED, void_type_node,
- gfc_trans_code (code->block->next), NULL_TREE);
+ code->block ? gfc_trans_code (code->block->next)
+ : NULL_TREE, omp_clauses);
}
static tree
@@ -3577,6 +3911,7 @@ enum
GFC_OMP_SPLIT_DISTRIBUTE,
GFC_OMP_SPLIT_TEAMS,
GFC_OMP_SPLIT_TARGET,
+ GFC_OMP_SPLIT_TASKLOOP,
GFC_OMP_SPLIT_NUM
};
@@ -3587,7 +3922,8 @@ enum
GFC_OMP_MASK_PARALLEL = (1 << GFC_OMP_SPLIT_PARALLEL),
GFC_OMP_MASK_DISTRIBUTE = (1 << GFC_OMP_SPLIT_DISTRIBUTE),
GFC_OMP_MASK_TEAMS = (1 << GFC_OMP_SPLIT_TEAMS),
- GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET)
+ GFC_OMP_MASK_TARGET = (1 << GFC_OMP_SPLIT_TARGET),
+ GFC_OMP_MASK_TASKLOOP = (1 << GFC_OMP_SPLIT_TASKLOOP)
};
static void
@@ -3638,6 +3974,23 @@ gfc_split_omp_clauses (gfc_code *code,
case EXEC_OMP_TARGET:
innermost = GFC_OMP_SPLIT_TARGET;
break;
+ case EXEC_OMP_TARGET_PARALLEL:
+ mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL;
+ innermost = GFC_OMP_SPLIT_PARALLEL;
+ break;
+ case EXEC_OMP_TARGET_PARALLEL_DO:
+ mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO;
+ innermost = GFC_OMP_SPLIT_DO;
+ break;
+ case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO
+ | GFC_OMP_MASK_SIMD;
+ innermost = GFC_OMP_SPLIT_SIMD;
+ break;
+ case EXEC_OMP_TARGET_SIMD:
+ mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_SIMD;
+ innermost = GFC_OMP_SPLIT_SIMD;
+ break;
case EXEC_OMP_TARGET_TEAMS:
mask = GFC_OMP_MASK_TARGET | GFC_OMP_MASK_TEAMS;
innermost = GFC_OMP_SPLIT_TEAMS;
@@ -3662,6 +4015,13 @@ gfc_split_omp_clauses (gfc_code *code,
| GFC_OMP_MASK_DISTRIBUTE | GFC_OMP_MASK_SIMD;
innermost = GFC_OMP_SPLIT_SIMD;
break;
+ case EXEC_OMP_TASKLOOP:
+ innermost = GFC_OMP_SPLIT_TASKLOOP;
+ break;
+ case EXEC_OMP_TASKLOOP_SIMD:
+ mask = GFC_OMP_MASK_TASKLOOP | GFC_OMP_MASK_SIMD;
+ innermost = GFC_OMP_SPLIT_SIMD;
+ break;
case EXEC_OMP_TEAMS:
innermost = GFC_OMP_SPLIT_TEAMS;
break;
@@ -3698,8 +4058,17 @@ gfc_split_omp_clauses (gfc_code *code,
/* First the clauses that are unique to some constructs. */
clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_MAP]
= code->ext.omp_clauses->lists[OMP_LIST_MAP];
+ clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_IS_DEVICE_PTR]
+ = code->ext.omp_clauses->lists[OMP_LIST_IS_DEVICE_PTR];
clausesa[GFC_OMP_SPLIT_TARGET].device
= code->ext.omp_clauses->device;
+ clausesa[GFC_OMP_SPLIT_TARGET].defaultmap
+ = code->ext.omp_clauses->defaultmap;
+ clausesa[GFC_OMP_SPLIT_TARGET].if_exprs[OMP_IF_TARGET]
+ = code->ext.omp_clauses->if_exprs[OMP_IF_TARGET];
+ /* And this is copied to all. */
+ clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
+ = code->ext.omp_clauses->if_expr;
}
if (mask & GFC_OMP_MASK_TEAMS)
{
@@ -3708,7 +4077,8 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->num_teams;
clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit
= code->ext.omp_clauses->thread_limit;
- /* Shared and default clauses are allowed on parallel and teams. */
+ /* Shared and default clauses are allowed on parallel, teams
+ and taskloop. */
clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_SHARED]
= code->ext.omp_clauses->lists[OMP_LIST_SHARED];
clausesa[GFC_OMP_SPLIT_TEAMS].default_sharing
@@ -3734,19 +4104,34 @@ gfc_split_omp_clauses (gfc_code *code,
= code->ext.omp_clauses->num_threads;
clausesa[GFC_OMP_SPLIT_PARALLEL].proc_bind
= code->ext.omp_clauses->proc_bind;
- /* Shared and default clauses are allowed on parallel and teams. */
+ /* Shared and default clauses are allowed on parallel, teams
+ and taskloop. */
clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_SHARED]
= code->ext.omp_clauses->lists[OMP_LIST_SHARED];
clausesa[GFC_OMP_SPLIT_PARALLEL].default_sharing
= code->ext.omp_clauses->default_sharing;
+ clausesa[GFC_OMP_SPLIT_PARALLEL].if_exprs[OMP_IF_PARALLEL]
+ = code->ext.omp_clauses->if_exprs[OMP_IF_PARALLEL];
+ /* And this is copied to all. */
+ clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
+ = code->ext.omp_clauses->if_expr;
}
if (mask & GFC_OMP_MASK_DO)
{
/* First the clauses that are unique to some constructs. */
clausesa[GFC_OMP_SPLIT_DO].ordered
= code->ext.omp_clauses->ordered;
+ clausesa[GFC_OMP_SPLIT_DO].orderedc
+ = code->ext.omp_clauses->orderedc;
clausesa[GFC_OMP_SPLIT_DO].sched_kind
= code->ext.omp_clauses->sched_kind;
+ if (innermost == GFC_OMP_SPLIT_SIMD)
+ clausesa[GFC_OMP_SPLIT_DO].sched_simd
+ = code->ext.omp_clauses->sched_simd;
+ clausesa[GFC_OMP_SPLIT_DO].sched_monotonic
+ = code->ext.omp_clauses->sched_monotonic;
+ clausesa[GFC_OMP_SPLIT_DO].sched_nonmonotonic
+ = code->ext.omp_clauses->sched_nonmonotonic;
clausesa[GFC_OMP_SPLIT_DO].chunk_size
= code->ext.omp_clauses->chunk_size;
clausesa[GFC_OMP_SPLIT_DO].nowait
@@ -3759,25 +4144,60 @@ gfc_split_omp_clauses (gfc_code *code,
{
clausesa[GFC_OMP_SPLIT_SIMD].safelen_expr
= code->ext.omp_clauses->safelen_expr;
- clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_LINEAR]
- = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
+ clausesa[GFC_OMP_SPLIT_SIMD].simdlen_expr
+ = code->ext.omp_clauses->simdlen_expr;
clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_ALIGNED]
= code->ext.omp_clauses->lists[OMP_LIST_ALIGNED];
/* Duplicate collapse. */
clausesa[GFC_OMP_SPLIT_SIMD].collapse
= code->ext.omp_clauses->collapse;
}
- /* Private clause is supported on all constructs but target,
+ if (mask & GFC_OMP_MASK_TASKLOOP)
+ {
+ /* First the clauses that are unique to some constructs. */
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].nogroup
+ = code->ext.omp_clauses->nogroup;
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].grainsize
+ = code->ext.omp_clauses->grainsize;
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].num_tasks
+ = code->ext.omp_clauses->num_tasks;
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].priority
+ = code->ext.omp_clauses->priority;
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].final_expr
+ = code->ext.omp_clauses->final_expr;
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].untied
+ = code->ext.omp_clauses->untied;
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].mergeable
+ = code->ext.omp_clauses->mergeable;
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].if_exprs[OMP_IF_TASKLOOP]
+ = code->ext.omp_clauses->if_exprs[OMP_IF_TASKLOOP];
+ /* And this is copied to all. */
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].if_expr
+ = code->ext.omp_clauses->if_expr;
+ /* Shared and default clauses are allowed on parallel, teams
+ and taskloop. */
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].lists[OMP_LIST_SHARED]
+ = code->ext.omp_clauses->lists[OMP_LIST_SHARED];
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].default_sharing
+ = code->ext.omp_clauses->default_sharing;
+ /* Duplicate collapse. */
+ clausesa[GFC_OMP_SPLIT_TASKLOOP].collapse
+ = code->ext.omp_clauses->collapse;
+ }
+ /* Private clause is supported on all constructs,
it is enough to put it on the innermost one. For
- !$ omp do put it on parallel though,
+ !$ omp parallel do put it on parallel though,
as that's what we did for OpenMP 3.1. */
clausesa[innermost == GFC_OMP_SPLIT_DO
? (int) GFC_OMP_SPLIT_PARALLEL
: innermost].lists[OMP_LIST_PRIVATE]
= code->ext.omp_clauses->lists[OMP_LIST_PRIVATE];
/* Firstprivate clause is supported on all constructs but
- target and simd. Put it on the outermost of those and
- duplicate on parallel. */
+ simd. Put it on the outermost of those and duplicate
+ on parallel and teams. */
+ if (mask & GFC_OMP_MASK_TARGET)
+ clausesa[GFC_OMP_SPLIT_TARGET].lists[OMP_LIST_FIRSTPRIVATE]
+ = code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
if (mask & GFC_OMP_MASK_TEAMS)
clausesa[GFC_OMP_SPLIT_TEAMS].lists[OMP_LIST_FIRSTPRIVATE]
= code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
@@ -3790,9 +4210,12 @@ gfc_split_omp_clauses (gfc_code *code,
else if (mask & GFC_OMP_MASK_DO)
clausesa[GFC_OMP_SPLIT_DO].lists[OMP_LIST_FIRSTPRIVATE]
= code->ext.omp_clauses->lists[OMP_LIST_FIRSTPRIVATE];
- /* Lastprivate is allowed on do and simd. In
- parallel do{, simd} we actually want to put it on
+ /* Lastprivate is allowed on distribute, do and simd.
+ In parallel do{, simd} we actually want to put it on
parallel rather than do. */
+ if (mask & GFC_OMP_MASK_DISTRIBUTE)
+ clausesa[GFC_OMP_SPLIT_DISTRIBUTE].lists[OMP_LIST_LASTPRIVATE]
+ = code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
if (mask & GFC_OMP_MASK_PARALLEL)
clausesa[GFC_OMP_SPLIT_PARALLEL].lists[OMP_LIST_LASTPRIVATE]
= code->ext.omp_clauses->lists[OMP_LIST_LASTPRIVATE];
@@ -3817,13 +4240,10 @@ gfc_split_omp_clauses (gfc_code *code,
if (mask & GFC_OMP_MASK_SIMD)
clausesa[GFC_OMP_SPLIT_SIMD].lists[OMP_LIST_REDUCTION]
= code->ext.omp_clauses->lists[OMP_LIST_REDUCTION];
- /* FIXME: This is currently being discussed. */
- if (mask & GFC_OMP_MASK_PARALLEL)
- clausesa[GFC_OMP_SPLIT_PARALLEL].if_expr
- = code->ext.omp_clauses->if_expr;
- else
- clausesa[GFC_OMP_SPLIT_TARGET].if_expr
- = code->ext.omp_clauses->if_expr;
+ /* Linear clause is supported on do and simd,
+ put it on the innermost one. */
+ clausesa[innermost].lists[OMP_LIST_LINEAR]
+ = code->ext.omp_clauses->lists[OMP_LIST_LINEAR];
}
if ((mask & (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
== (GFC_OMP_MASK_PARALLEL | GFC_OMP_MASK_DO))
@@ -4166,11 +4586,12 @@ gfc_trans_omp_distribute (gfc_code *code, gfc_omp_clauses *clausesa)
}
static tree
-gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa)
+gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa,
+ tree omp_clauses)
{
stmtblock_t block;
gfc_omp_clauses clausesa_buf[GFC_OMP_SPLIT_NUM];
- tree stmt, omp_clauses = NULL_TREE;
+ tree stmt;
bool combined = true;
gfc_start_block (&block);
@@ -4181,8 +4602,9 @@ gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa)
}
if (flag_openmp)
omp_clauses
- = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TEAMS],
- code->loc);
+ = chainon (omp_clauses,
+ gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TEAMS],
+ code->loc));
switch (code->op)
{
case EXEC_OMP_TARGET_TEAMS:
@@ -4200,10 +4622,13 @@ gfc_trans_omp_teams (gfc_code *code, gfc_omp_clauses *clausesa)
stmt = gfc_trans_omp_distribute (code, clausesa);
break;
}
- stmt = build2_loc (input_location, OMP_TEAMS, void_type_node, stmt,
- omp_clauses);
- if (combined)
- OMP_TEAMS_COMBINED (stmt) = 1;
+ if (flag_openmp)
+ {
+ stmt = build2_loc (input_location, OMP_TEAMS, void_type_node, stmt,
+ omp_clauses);
+ if (combined)
+ OMP_TEAMS_COMBINED (stmt) = 1;
+ }
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
}
@@ -4221,24 +4646,128 @@ gfc_trans_omp_target (gfc_code *code)
omp_clauses
= gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TARGET],
code->loc);
- if (code->op == EXEC_OMP_TARGET)
+ switch (code->op)
{
+ case EXEC_OMP_TARGET:
pushlevel ();
stmt = gfc_trans_omp_code (code->block->next, true);
stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
+ break;
+ case EXEC_OMP_TARGET_PARALLEL:
+ {
+ stmtblock_t iblock;
+
+ gfc_start_block (&iblock);
+ tree inner_clauses
+ = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_PARALLEL],
+ code->loc);
+ stmt = gfc_trans_omp_code (code->block->next, true);
+ stmt = build2_loc (input_location, OMP_PARALLEL, void_type_node, stmt,
+ inner_clauses);
+ gfc_add_expr_to_block (&iblock, stmt);
+ stmt = gfc_finish_block (&iblock);
+ if (TREE_CODE (stmt) != BIND_EXPR)
+ stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
+ else
+ poplevel (0, 0);
+ }
+ break;
+ case EXEC_OMP_TARGET_PARALLEL_DO:
+ case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ stmt = gfc_trans_omp_parallel_do (code, &block, clausesa);
+ if (TREE_CODE (stmt) != BIND_EXPR)
+ stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
+ else
+ poplevel (0, 0);
+ break;
+ case EXEC_OMP_TARGET_SIMD:
+ stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
+ &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
+ if (TREE_CODE (stmt) != BIND_EXPR)
+ stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
+ else
+ poplevel (0, 0);
+ break;
+ default:
+ if (flag_openmp
+ && (clausesa[GFC_OMP_SPLIT_TEAMS].num_teams
+ || clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit))
+ {
+ gfc_omp_clauses clausesb;
+ tree teams_clauses;
+ /* For combined !$omp target teams, the num_teams and
+ thread_limit clauses are evaluated before entering the
+ target construct. */
+ memset (&clausesb, '\0', sizeof (clausesb));
+ clausesb.num_teams = clausesa[GFC_OMP_SPLIT_TEAMS].num_teams;
+ clausesb.thread_limit = clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit;
+ clausesa[GFC_OMP_SPLIT_TEAMS].num_teams = NULL;
+ clausesa[GFC_OMP_SPLIT_TEAMS].thread_limit = NULL;
+ teams_clauses
+ = gfc_trans_omp_clauses (&block, &clausesb, code->loc);
+ pushlevel ();
+ stmt = gfc_trans_omp_teams (code, clausesa, teams_clauses);
+ }
+ else
+ {
+ pushlevel ();
+ stmt = gfc_trans_omp_teams (code, clausesa, NULL_TREE);
+ }
+ if (TREE_CODE (stmt) != BIND_EXPR)
+ stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
+ else
+ poplevel (0, 0);
+ break;
}
- else
+ if (flag_openmp)
{
- pushlevel ();
- stmt = gfc_trans_omp_teams (code, clausesa);
+ stmt = build2_loc (input_location, OMP_TARGET, void_type_node, stmt,
+ omp_clauses);
+ if (code->op != EXEC_OMP_TARGET)
+ OMP_TARGET_COMBINED (stmt) = 1;
+ }
+ gfc_add_expr_to_block (&block, stmt);
+ return gfc_finish_block (&block);
+}
+
+static tree
+gfc_trans_omp_taskloop (gfc_code *code)
+{
+ stmtblock_t block;
+ gfc_omp_clauses clausesa[GFC_OMP_SPLIT_NUM];
+ tree stmt, omp_clauses = NULL_TREE;
+
+ gfc_start_block (&block);
+ gfc_split_omp_clauses (code, clausesa);
+ if (flag_openmp)
+ omp_clauses
+ = gfc_trans_omp_clauses (&block, &clausesa[GFC_OMP_SPLIT_TASKLOOP],
+ code->loc);
+ switch (code->op)
+ {
+ case EXEC_OMP_TASKLOOP:
+ /* This is handled in gfc_trans_omp_do. */
+ gcc_unreachable ();
+ break;
+ case EXEC_OMP_TASKLOOP_SIMD:
+ stmt = gfc_trans_omp_do (code, EXEC_OMP_SIMD, &block,
+ &clausesa[GFC_OMP_SPLIT_SIMD], NULL_TREE);
if (TREE_CODE (stmt) != BIND_EXPR)
stmt = build3_v (BIND_EXPR, NULL, stmt, poplevel (1, 0));
else
poplevel (0, 0);
+ break;
+ default:
+ gcc_unreachable ();
}
if (flag_openmp)
- stmt = build2_loc (input_location, OMP_TARGET, void_type_node, stmt,
- omp_clauses);
+ {
+ tree taskloop = make_node (OMP_TASKLOOP);
+ TREE_TYPE (taskloop) = void_type_node;
+ OMP_FOR_BODY (taskloop) = stmt;
+ OMP_FOR_CLAUSES (taskloop) = omp_clauses;
+ stmt = taskloop;
+ }
gfc_add_expr_to_block (&block, stmt);
return gfc_finish_block (&block);
}
@@ -4260,6 +4789,36 @@ gfc_trans_omp_target_data (gfc_code *code)
}
static tree
+gfc_trans_omp_target_enter_data (gfc_code *code)
+{
+ stmtblock_t block;
+ tree stmt, omp_clauses;
+
+ gfc_start_block (&block);
+ omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
+ code->loc);
+ stmt = build1_loc (input_location, OMP_TARGET_ENTER_DATA, void_type_node,
+ omp_clauses);
+ gfc_add_expr_to_block (&block, stmt);
+ return gfc_finish_block (&block);
+}
+
+static tree
+gfc_trans_omp_target_exit_data (gfc_code *code)
+{
+ stmtblock_t block;
+ tree stmt, omp_clauses;
+
+ gfc_start_block (&block);
+ omp_clauses = gfc_trans_omp_clauses (&block, code->ext.omp_clauses,
+ code->loc);
+ stmt = build1_loc (input_location, OMP_TARGET_EXIT_DATA, void_type_node,
+ omp_clauses);
+ gfc_add_expr_to_block (&block, stmt);
+ return gfc_finish_block (&block);
+}
+
+static tree
gfc_trans_omp_target_update (gfc_code *code)
{
stmtblock_t block;
@@ -4503,6 +5062,7 @@ gfc_trans_omp_directive (gfc_code *code)
case EXEC_OMP_DISTRIBUTE:
case EXEC_OMP_DO:
case EXEC_OMP_SIMD:
+ case EXEC_OMP_TASKLOOP:
return gfc_trans_omp_do (code, code->op, NULL, code->ext.omp_clauses,
NULL);
case EXEC_OMP_DISTRIBUTE_PARALLEL_DO:
@@ -4532,6 +5092,10 @@ gfc_trans_omp_directive (gfc_code *code)
case EXEC_OMP_SINGLE:
return gfc_trans_omp_single (code, code->ext.omp_clauses);
case EXEC_OMP_TARGET:
+ case EXEC_OMP_TARGET_PARALLEL:
+ case EXEC_OMP_TARGET_PARALLEL_DO:
+ case EXEC_OMP_TARGET_PARALLEL_DO_SIMD:
+ case EXEC_OMP_TARGET_SIMD:
case EXEC_OMP_TARGET_TEAMS:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE:
case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO:
@@ -4540,12 +5104,18 @@ gfc_trans_omp_directive (gfc_code *code)
return gfc_trans_omp_target (code);
case EXEC_OMP_TARGET_DATA:
return gfc_trans_omp_target_data (code);
+ case EXEC_OMP_TARGET_ENTER_DATA:
+ return gfc_trans_omp_target_enter_data (code);
+ case EXEC_OMP_TARGET_EXIT_DATA:
+ return gfc_trans_omp_target_exit_data (code);
case EXEC_OMP_TARGET_UPDATE:
return gfc_trans_omp_target_update (code);
case EXEC_OMP_TASK:
return gfc_trans_omp_task (code);
case EXEC_OMP_TASKGROUP:
return gfc_trans_omp_taskgroup (code);
+ case EXEC_OMP_TASKLOOP_SIMD:
+ return gfc_trans_omp_taskloop (code);
case EXEC_OMP_TASKWAIT:
return gfc_trans_omp_taskwait ();
case EXEC_OMP_TASKYIELD:
@@ -4555,7 +5125,7 @@ gfc_trans_omp_directive (gfc_code *code)
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO:
case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD:
case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD:
- return gfc_trans_omp_teams (code, NULL);
+ return gfc_trans_omp_teams (code, NULL, NULL_TREE);
case EXEC_OMP_WORKSHARE:
return gfc_trans_omp_workshare (code, code->ext.omp_clauses);
default: