loop that follows. N is an integer constant specifying the unrolling factor.
The values of 0 and 1 block any unrolling of the loop.
+For @code{DO CONCURRENT} constructs the unrolling specification applies
+only to the first loop control variable.
+
@node BUILTIN directive
@subsection BUILTIN directive
dependencies between iterations. The purpose of the directive is to
tell the compiler that vectorization is safe.
+For @code{DO CONCURRENT} constructs this annotation is implicit to all
+loop control variables.
+
This directive is intended for annotation of existing code. For new
code it is recommended to consider OpenMP SIMD directives as potential
alternative.
must be placed immediately before a @code{DO} loop and applies only to
the loop that follows.
+For @code{DO CONCURRENT} constructs this annotation applies to all loops
+specified in the concurrent header.
+
@node NOVECTOR directive
@subsection NOVECTOR directive
It must be placed immediately before a @code{DO} loop and applies only
to the loop that follows.
+For @code{DO CONCURRENT} constructs this annotation applies to all loops
+specified in the concurrent header.
+
@node Non-Fortran Main Program
@section Non-Fortran Main Program
do_op = new_st.op;
s.ext.end_do_label = new_st.label1;
- if (new_st.ext.iterator != NULL)
+ if (do_op == EXEC_DO_CONCURRENT)
+ {
+ gfc_forall_iterator *fa;
+ for (fa = new_st.ext.forall_iterator; fa; fa = fa->next)
+ {
+ /* Apply unroll only to innermost loop (first control
+ variable). */
+ if (directive_unroll != -1)
+ {
+ fa->annot.unroll = directive_unroll;
+ directive_unroll = -1;
+ }
+ if (directive_ivdep)
+ fa->annot.ivdep = directive_ivdep;
+ if (directive_vector)
+ fa->annot.vector = directive_vector;
+ if (directive_novector)
+ fa->annot.novector = directive_novector;
+ }
+ directive_ivdep = false;
+ directive_vector = false;
+ directive_novector = false;
+ stree = NULL;
+ }
+ else if (new_st.ext.iterator != NULL)
{
stree = new_st.ext.iterator->var->symtree;
if (directive_unroll != -1)
{
- new_st.ext.iterator->unroll = directive_unroll;
+ new_st.ext.iterator->annot.unroll = directive_unroll;
directive_unroll = -1;
}
if (directive_ivdep)
{
- new_st.ext.iterator->ivdep = directive_ivdep;
+ new_st.ext.iterator->annot.ivdep = directive_ivdep;
directive_ivdep = false;
}
if (directive_vector)
{
- new_st.ext.iterator->vector = directive_vector;
+ new_st.ext.iterator->annot.vector = directive_vector;
directive_vector = false;
}
if (directive_novector)
{
- new_st.ext.iterator->novector = directive_novector;
+ new_st.ext.iterator->annot.novector = directive_novector;
directive_novector = false;
}
}
tree start;
tree end;
tree step;
+ gfc_loop_annot annot;
struct iter_info *next;
}
iter_info;
fold_convert (type, to));
cond = gfc_evaluate_now_loc (loc, cond, &body);
- if (code->ext.iterator->unroll && cond != error_mark_node)
+ if (code->ext.iterator->annot.unroll && cond != error_mark_node)
cond
= build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_unroll_kind),
- build_int_cst (integer_type_node, code->ext.iterator->unroll));
+ build_int_cst (integer_type_node,
+ code->ext.iterator->annot.unroll));
- if (code->ext.iterator->ivdep && cond != error_mark_node)
+ if (code->ext.iterator->annot.ivdep && cond != error_mark_node)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_ivdep_kind),
integer_zero_node);
- if (code->ext.iterator->vector && cond != error_mark_node)
+ if (code->ext.iterator->annot.vector && cond != error_mark_node)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_vector_kind),
integer_zero_node);
- if (code->ext.iterator->novector && cond != error_mark_node)
+ if (code->ext.iterator->annot.novector && cond != error_mark_node)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_no_vector_kind),
integer_zero_node);
/* End with the loop condition. Loop until countm1t == 0. */
cond = fold_build2_loc (loc, EQ_EXPR, logical_type_node, countm1t,
build_int_cst (utype, 0));
- if (code->ext.iterator->unroll && cond != error_mark_node)
+ if (code->ext.iterator->annot.unroll && cond != error_mark_node)
cond
= build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_unroll_kind),
- build_int_cst (integer_type_node, code->ext.iterator->unroll));
+ build_int_cst (integer_type_node,
+ code->ext.iterator->annot.unroll));
- if (code->ext.iterator->ivdep && cond != error_mark_node)
+ if (code->ext.iterator->annot.ivdep && cond != error_mark_node)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_ivdep_kind),
integer_zero_node);
- if (code->ext.iterator->vector && cond != error_mark_node)
+ if (code->ext.iterator->annot.vector && cond != error_mark_node)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_vector_kind),
integer_zero_node);
- if (code->ext.iterator->novector && cond != error_mark_node)
+ if (code->ext.iterator->annot.novector && cond != error_mark_node)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_no_vector_kind),
integer_zero_node);
/* PR 83064 means that we cannot use annot_expr_parallel_kind until
the autoparallelizer can handle this. */
- if (forall_tmp->do_concurrent)
+ if (forall_tmp->do_concurrent || iter->annot.ivdep)
cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node,
annot_expr_ivdep_kind),
integer_zero_node);
+ if (iter->annot.unroll && cond != error_mark_node)
+ cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node,
+ annot_expr_unroll_kind),
+ build_int_cst (integer_type_node, iter->annot.unroll));
+
+ if (iter->annot.vector && cond != error_mark_node)
+ cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node,
+ annot_expr_vector_kind),
+ integer_zero_node);
+
+ if (iter->annot.novector && cond != error_mark_node)
+ cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
+ build_int_cst (integer_type_node,
+ annot_expr_no_vector_kind),
+ integer_zero_node);
+
tmp = build1_v (GOTO_EXPR, exit_label);
tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node,
cond, tmp, build_empty_stmt (input_location));
gfc_add_block_to_block (&block, &se.pre);
step[n] = se.expr;
+ /* Copy loop annotations. */
+ this_forall->annot = fa->annot;
+
/* Set the NEXT field of this_forall to NULL. */
this_forall->next = NULL;
/* Link this_forall to the info construct. */