From: Harald Anlauf <anlauf@gmx.de>
To: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Cc: fortran <fortran@gcc.gnu.org>, gcc-patches <gcc-patches@gcc.gnu.org>
Subject: [PATCH, v2] Fortran: annotations for DO CONCURRENT loops [PR113305]
Date: Fri, 12 Jan 2024 20:23:20 +0100 [thread overview]
Message-ID: <5ccdd809-5483-42df-8cc2-965584285ecf@gmx.de> (raw)
In-Reply-To: <20240112104432.3466b1e9@nbbrfq.loc>
[-- Attachment #1: Type: text/plain, Size: 1768 bytes --]
Hi Bernhard,
On 1/12/24 10:44, Bernhard Reutner-Fischer wrote:
> On Wed, 10 Jan 2024 23:24:22 +0100
> Harald Anlauf <anlauf@gmx.de> wrote:
>
>> diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
>> index 82f388c05f8..88502c1e3f0 100644
>> --- a/gcc/fortran/gfortran.h
>> +++ b/gcc/fortran/gfortran.h
>> @@ -2926,6 +2926,10 @@ gfc_dt;
>> typedef struct gfc_forall_iterator
>> {
>> gfc_expr *var, *start, *end, *stride;
>> + unsigned short unroll;
>> + bool ivdep;
>> + bool vector;
>> + bool novector;
>> struct gfc_forall_iterator *next;
>> }
> []
>> diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
>> index a718dce237f..59a9cf99f9b 100644
>> --- a/gcc/fortran/trans-stmt.cc
>> +++ b/gcc/fortran/trans-stmt.cc
>> @@ -41,6 +41,10 @@ typedef struct iter_info
>> tree start;
>> tree end;
>> tree step;
>> + unsigned short unroll;
>> + bool ivdep;
>> + bool vector;
>> + bool novector;
>> struct iter_info *next;
>> }
>
> Given that we already have in gfortran.h
>
>> typedef struct
>> {
>> gfc_expr *var, *start, *end, *step;
>> unsigned short unroll;
>> bool ivdep;
>> bool vector;
>> bool novector;
>> }
>> gfc_iterator;
>
> would it make sense to break out these loop annotation flags into its
> own let's say struct gfc_iterator_flags and use pointers to that flags
> instead?
I've created a struct gfc_loop_annot and use that directly
as I think using pointers to it is probably not very efficient.
Well, the struct is smaller than a pointer on a 64-bit system...
> LGTM otherwise.
> Thanks for the patch!
Thanks for the review!
If there are no further comments, I'll commit the attached version
soon.
Harald
[-- Attachment #2: pr113305-v2.diff --]
[-- Type: text/x-patch, Size: 12342 bytes --]
From 31d8957a95455663577a0e60109679d56aac234d Mon Sep 17 00:00:00 2001
From: Harald Anlauf <anlauf@gmx.de>
Date: Fri, 12 Jan 2024 19:51:11 +0100
Subject: [PATCH] Fortran: annotations for DO CONCURRENT loops [PR113305]
gcc/fortran/ChangeLog:
PR fortran/113305
* gfortran.h (gfc_loop_annot): New.
(gfc_iterator, gfc_forall_iterator): Use for annotation control.
* array.cc (gfc_copy_iterator): Adjust.
* gfortran.texi: Document annotations IVDEP, UNROLL n, VECTOR,
NOVECTOR as applied to DO CONCURRENT.
* parse.cc (parse_do_block): Parse annotations IVDEP, UNROLL n,
VECTOR, NOVECTOR as applied to DO CONCURRENT. Apply UNROLL only to
first loop control variable.
* trans-stmt.cc (iter_info): Use gfc_loop_annot.
(gfc_trans_simple_do): Adjust.
(gfc_trans_forall_loop): Annotate loops with IVDEP, UNROLL n,
VECTOR, NOVECTOR as needed for DO CONCURRENT.
(gfc_trans_forall_1): Handle loop annotations.
gcc/testsuite/ChangeLog:
PR fortran/113305
* gfortran.dg/do_concurrent_7.f90: New test.
---
gcc/fortran/array.cc | 5 +-
gcc/fortran/gfortran.h | 11 ++++-
gcc/fortran/gfortran.texi | 12 +++++
gcc/fortran/parse.cc | 34 ++++++++++++--
gcc/fortran/trans-stmt.cc | 46 ++++++++++++++-----
gcc/testsuite/gfortran.dg/do_concurrent_7.f90 | 26 +++++++++++
6 files changed, 113 insertions(+), 21 deletions(-)
create mode 100644 gcc/testsuite/gfortran.dg/do_concurrent_7.f90
diff --git a/gcc/fortran/array.cc b/gcc/fortran/array.cc
index 19456baf103..81fa99d219f 100644
--- a/gcc/fortran/array.cc
+++ b/gcc/fortran/array.cc
@@ -2308,10 +2308,7 @@ gfc_copy_iterator (gfc_iterator *src)
dest->start = gfc_copy_expr (src->start);
dest->end = gfc_copy_expr (src->end);
dest->step = gfc_copy_expr (src->step);
- dest->unroll = src->unroll;
- dest->ivdep = src->ivdep;
- dest->vector = src->vector;
- dest->novector = src->novector;
+ dest->annot = src->annot;
return dest;
}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 82f388c05f8..fd73e4ce431 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2830,14 +2830,22 @@ gfc_case;
#define gfc_get_case() XCNEW (gfc_case)
+/* Annotations for loop constructs. */
typedef struct
{
- gfc_expr *var, *start, *end, *step;
unsigned short unroll;
bool ivdep;
bool vector;
bool novector;
}
+gfc_loop_annot;
+
+
+typedef struct
+{
+ gfc_expr *var, *start, *end, *step;
+ gfc_loop_annot annot;
+}
gfc_iterator;
#define gfc_get_iterator() XCNEW (gfc_iterator)
@@ -2926,6 +2934,7 @@ gfc_dt;
typedef struct gfc_forall_iterator
{
gfc_expr *var, *start, *end, *stride;
+ gfc_loop_annot annot;
struct gfc_forall_iterator *next;
}
gfc_forall_iterator;
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index 5615fee2897..371666dcbb6 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -3262,6 +3262,9 @@ It must be placed immediately before a @code{DO} loop and applies only to the
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
@@ -3300,6 +3303,9 @@ whether a particular loop is vectorizable due to potential
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.
@@ -3316,6 +3322,9 @@ This directive tells the compiler to vectorize the following loop. 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 NOVECTOR directive
@subsection NOVECTOR directive
@@ -3328,6 +3337,9 @@ This directive tells the compiler to not vectorize the following loop.
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
diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc
index d8b38cfb5ac..98a04e72a93 100644
--- a/gcc/fortran/parse.cc
+++ b/gcc/fortran/parse.cc
@@ -5307,27 +5307,51 @@ parse_do_block (void)
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;
}
}
diff --git a/gcc/fortran/trans-stmt.cc b/gcc/fortran/trans-stmt.cc
index a718dce237f..5247d3d39d7 100644
--- a/gcc/fortran/trans-stmt.cc
+++ b/gcc/fortran/trans-stmt.cc
@@ -41,6 +41,7 @@ typedef struct iter_info
tree start;
tree end;
tree step;
+ gfc_loop_annot annot;
struct iter_info *next;
}
iter_info;
@@ -2462,21 +2463,22 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar,
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);
@@ -2806,21 +2808,22 @@ gfc_trans_do (gfc_code * code, tree exit_cond)
/* 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);
@@ -4117,12 +4120,30 @@ gfc_trans_forall_loop (forall_info *forall_tmp, tree body,
/* 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));
@@ -5090,6 +5111,9 @@ gfc_trans_forall_1 (gfc_code * code, forall_info * nested_forall_info)
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. */
diff --git a/gcc/testsuite/gfortran.dg/do_concurrent_7.f90 b/gcc/testsuite/gfortran.dg/do_concurrent_7.f90
new file mode 100644
index 00000000000..604f6712d05
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/do_concurrent_7.f90
@@ -0,0 +1,26 @@
+! { dg-do compile }
+! { dg-additional-options "-fdump-tree-original" }
+! PR fortran/113305
+
+program dc
+ implicit none
+ real :: a(12), b(12), c(16,8), d(16,8)
+ integer :: i, j
+ call random_number(b)
+!GCC$ ivdep
+!GCC$ vector
+ do concurrent (i=1:12)
+ a(i) = 2*b(i)
+ end do
+ c = b(1)
+ d = a(2)
+!GCC$ novector
+!GCC$ unroll 4
+ do concurrent (i=1:16:2,j=1:8:2)
+ d(i,j) = 3*c(i,j)
+ end do
+end program
+
+! { dg-final { scan-tree-dump "ANNOTATE_EXPR .* ivdep>, vector" "original" } }
+! { dg-final { scan-tree-dump "ANNOTATE_EXPR .* ivdep>, no-vector" "original" } }
+! { dg-final { scan-tree-dump "ANNOTATE_EXPR .* ivdep>, unroll 4>, no-vector" "original" } }
--
2.35.3
prev parent reply other threads:[~2024-01-12 19:23 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-01-10 22:24 [PATCH] " Harald Anlauf
2024-01-12 9:44 ` Bernhard Reutner-Fischer
2024-01-12 19:23 ` Harald Anlauf [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5ccdd809-5483-42df-8cc2-965584285ecf@gmx.de \
--to=anlauf@gmx.de \
--cc=fortran@gcc.gnu.org \
--cc=gcc-patches@gcc.gnu.org \
--cc=rep.dot.nop@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).