From: Cesar Philippidis <cesar@codesourcery.com>
To: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>,
Fortran List <fortran@gcc.gnu.org>,
Jakub Jelinek <jakub@redhat.com>
Subject: Re: [openacc] Teach gfortran to lower OpenACC routine dims
Date: Thu, 20 Sep 2018 14:41:00 -0000 [thread overview]
Message-ID: <ed6258d2-d706-94db-77d8-500e2fe45f9b@codesourcery.com> (raw)
In-Reply-To: <20180920002718.6b610881@nbbrfq.cc.univie.ac.at>
On 09/19/2018 03:27 PM, Bernhard Reutner-Fischer wrote:
> On Wed, 5 Sep 2018 12:52:03 -0700
> Cesar Philippidis <cesar@codesourcery.com> wrote:
>
>> At present, gfortran does not encode the gang, worker or vector
>> parallelism clauses when it creates acc routines dim attribute for
>> subroutines and functions. While support for acc routine is lacking in
>> other areas in gfortran (including modules), this patch is important
>> because it encodes the parallelism attributes using the same function
>> as the C and C++ FEs. This will become important with the forthcoming
>> nvptx vector length extensions, because large vectors are not
>> supported in acc routines yet.
>>
>> Is this OK for trunk? I regtested and bootstrapped for x86_64 with
>> nvptx offloading.
>
>> diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
>> index 94a7f7eaa50..d48c9351e25 100644
>> --- a/gcc/fortran/openmp.c
>> +++ b/gcc/fortran/openmp.c
>> @@ -2234,34 +2234,45 @@ gfc_match_oacc_cache (void)
>> return MATCH_YES;
>> }
>>
>> -/* Determine the loop level for a routine. */
>> +/* Determine the loop level for a routine. Returns
>> OACC_FUNCTION_NONE
>> + if any error is detected. */
>>
>> -static int
>> +static oacc_function
>> gfc_oacc_routine_dims (gfc_omp_clauses *clauses)
>> {
>> int level = -1;
>> + oacc_function ret = OACC_FUNCTION_AUTO;
>>
>> if (clauses)
>> {
>> unsigned mask = 0;
>>
>> if (clauses->gang)
>> - level = GOMP_DIM_GANG, mask |= GOMP_DIM_MASK (level);
>> + {
>> + level = GOMP_DIM_GANG, mask |= GOMP_DIM_MASK (level);
>> + ret = OACC_FUNCTION_GANG;
>> + }
>> if (clauses->worker)
>> - level = GOMP_DIM_WORKER, mask |= GOMP_DIM_MASK (level);
>> + {
>> + level = GOMP_DIM_WORKER, mask |= GOMP_DIM_MASK (level);
>> + ret = OACC_FUNCTION_WORKER;
>> + }
>> if (clauses->vector)
>> - level = GOMP_DIM_VECTOR, mask |= GOMP_DIM_MASK (level);
>> + {
>> + level = GOMP_DIM_VECTOR, mask |= GOMP_DIM_MASK (level);
>> + ret = OACC_FUNCTION_VECTOR;
>> + }
>> if (clauses->seq)
>> - level = GOMP_DIM_MAX, mask |= GOMP_DIM_MASK (level);
>> + {
>> + level = GOMP_DIM_MAX, mask |= GOMP_DIM_MASK (level);
>> + ret = OACC_FUNCTION_SEQ;
>> + }
>>
>> if (mask != (mask & -mask))
>> - gfc_error ("Multiple loop axes specified for routine");
>> + ret = OACC_FUNCTION_NONE;
>> }
>>
>> - if (level < 0)
>> - level = GOMP_DIM_MAX;
>> -
>> - return level;
>> + return ret;
>> }
>>
>> match
>> @@ -2272,6 +2283,8 @@ gfc_match_oacc_routine (void)
>> match m;
>> gfc_omp_clauses *c = NULL;
>> gfc_oacc_routine_name *n = NULL;
>> + oacc_function dims = OACC_FUNCTION_NONE;
>
> Unneeded initialisation of dims.
ACK.
>> + bool seen_error = false;
>>
>> old_loc = gfc_current_locus;
>>
>> @@ -2318,17 +2331,15 @@ gfc_match_oacc_routine (void)
>> }
>> else
>> {
>> - gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C");
>> - gfc_current_locus = old_loc;
>> - return MATCH_ERROR;
>> + gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %L",
>> &old_loc);
>> + goto cleanup;
>> }
>>
>> if (gfc_match_char (')') != MATCH_YES)
>> {
>> - gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %C,
>> expecting"
>> - " ')' after NAME");
>> - gfc_current_locus = old_loc;
>> - return MATCH_ERROR;
>> + gfc_error ("Syntax error in !$ACC ROUTINE ( NAME ) at %L,
>> expecting"
>> + " ')' after NAME", &old_loc);
>> + goto cleanup;
>> }
>> }
>>
>> @@ -2337,26 +2348,83 @@ gfc_match_oacc_routine (void)
>> != MATCH_YES))
>> return MATCH_ERROR;
>>
>> + /* Scan for invalid routine geometry. */
>> + dims = gfc_oacc_routine_dims (c);
>> + if (dims == OACC_FUNCTION_NONE)
>> + {
>> + gfc_error ("Multiple loop axes specified in !$ACC ROUTINE at
>> %L",
>> + &old_loc);
>> +
>> + /* Don't abort early, because it's important to let the user
>> + know of any potential duplicate routine directives. */
>> + seen_error = true;
>> + }
>> + else if (dims == OACC_FUNCTION_AUTO)
>> + {
>> + gfc_warning (0, "Expected one of %<gang%>, %<worker%>,
>> %<vector%> or "
>> + "%<seq%> clauses in !$ACC ROUTINE at %L",
>> &old_loc);
>> + dims = OACC_FUNCTION_SEQ;
>> + }
>> +
>> if (sym != NULL)
>> {
>> - n = gfc_get_oacc_routine_name ();
>> - n->sym = sym;
>> - n->clauses = NULL;
>> - n->next = NULL;
>> - if (gfc_current_ns->oacc_routine_names != NULL)
>> - n->next = gfc_current_ns->oacc_routine_names;
>> -
>> - gfc_current_ns->oacc_routine_names = n;
>> + bool needs_entry = true;
>> +
>> + /* Scan for any repeated routine directives on 'sym' and report
>> + an error if necessary. TODO: Extend this function to scan
>> + for compatible DEVICE_TYPE dims. */
>> + for (n = gfc_current_ns->oacc_routine_names; n; n = n->next)
>> + if (n->sym == sym)
>> + {
>> + needs_entry = false;
>> + if (dims != gfc_oacc_routine_dims (n->clauses))
>> + {
>> + gfc_error ("$!ACC ROUTINE already applied at %L",
>> &old_loc);
>> + goto cleanup;
>> + }
>> + }
>> +
>> + if (needs_entry)
>> + {
>> + n = gfc_get_oacc_routine_name ();
>> + n->sym = sym;
>> + n->clauses = c;
>> + n->next = NULL;
>> + n->loc = old_loc;
>> +
>> + if (gfc_current_ns->oacc_routine_names != NULL)
>> + n->next = gfc_current_ns->oacc_routine_names;
>
> Just omit n->next = NULL above and unconditionally set ->next to current
> ns' routine names.
ACK.
>> +
>> + gfc_current_ns->oacc_routine_names = n;
>> + }
>> +
>> + if (seen_error)
>> + goto cleanup;
>> }
>> else if (gfc_current_ns->proc_name)
>> {
>> + if (gfc_current_ns->proc_name->attr.oacc_function !=
>> OACC_FUNCTION_NONE
>> + && !seen_error)
>> + {
>> + gfc_error ("!$ACC ROUTINE already applied at %L",
>> &old_loc);
>> + goto cleanup;
>
> I'd move both this gfc_error and the one above to a duplicate_routine
> label before the cleanup label and jump to that here and for the
> identical gfc_error above.
I did it this way because we have a forthcoming patch which adds support
for Fortran modules, and that patch has a different set of errors. That
said, I'll incorporate those changes and modify the patch.
>> + }
>> +
>> if (!gfc_add_omp_declare_target
>> (&gfc_current_ns->proc_name->attr, gfc_current_ns->proc_name->name,
>> &old_loc))
>> goto cleanup;
>> +
>> gfc_current_ns->proc_name->attr.oacc_function
>> - = gfc_oacc_routine_dims (c) + 1;
>> + = seen_error ? OACC_FUNCTION_SEQ : dims;
>
> why can't you use dims unconditionally after branching to cleanup if
> seen_error? I.e. move the seen_error check below to above the
> attr.oacc_function setting?
Yeah, it probably doesn't matter much if the function returns
MATCH_ERROR. I'll change it.
>> +
>> + if (seen_error)
>> + goto cleanup;
>> }
>> + else
>> + /* Something has gone wrong. Perhaps there was a syntax error
>> + in the program-stmt. */
>> + goto cleanup;
>>
>> if (n)
>> n->clauses = c;
>> diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
>> index eea6b81ebfa..eed868f475b 100644
>> --- a/gcc/fortran/trans-decl.c
>> +++ b/gcc/fortran/trans-decl.c
>> @@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
>> #include "trans-stmt.h"
>> #include "gomp-constants.h"
>> #include "gimplify.h"
>> +#include "omp-general.h"
>
> hmz. so the gomp-constants.h include would be redundant, but do we
> really need omp-general.h?
Good point. omp-general.h is required for oacc_build_routine_dims.
> Doesn't this suggest to move this oacc dims lowering to trans-openmp.c
> instead, please?
So something like adding a new gfc_add_omp_offload_attributes to
trans-openmp.c and call it from add_attributes_to_decl?
>> #define MAX_LABEL_VALUE 99999
>>
>> @@ -1403,16 +1404,29 @@ add_attributes_to_decl (symbol_attribute
>> sym_attr, tree list) list = tree_cons (get_identifier ("omp declare
>> target"), NULL_TREE, list);
>>
>> - if (sym_attr.oacc_function)
>> + if (sym_attr.oacc_function != OACC_FUNCTION_NONE)
>> {
>> - tree dims = NULL_TREE;
>> - int ix;
>> - int level = sym_attr.oacc_function - 1;
>> + omp_clause_code code = OMP_CLAUSE_ERROR;
>
> redundant initialization.
ACK.
>> + tree clause, dims;
>>
>> - for (ix = GOMP_DIM_MAX; ix--;)
>> - dims = tree_cons (build_int_cst (boolean_type_node, ix >=
>> level),
>> - integer_zero_node, dims);
>> + switch (sym_attr.oacc_function)
>> + {
>> + case OACC_FUNCTION_GANG:
>> + code = OMP_CLAUSE_GANG;
>> + break;
>> + case OACC_FUNCTION_WORKER:
>> + code = OMP_CLAUSE_WORKER;
>> + break;
>> + case OACC_FUNCTION_VECTOR:
>> + code = OMP_CLAUSE_VECTOR;
>> + break;
>> + case OACC_FUNCTION_SEQ:
>> + default:
>> + code = OMP_CLAUSE_SEQ;
>> + }
>>
>> + clause = build_omp_clause (UNKNOWN_LOCATION, code);
>> + dims = oacc_build_routine_dims (clause);
>> list = tree_cons (get_identifier ("oacc function"),
>> dims, list);
>> }
On a related note, I noticed that I forgot to incorporate this change in
gfortran.h:
@@ -902,7 +912,7 @@ typedef struct
unsigned oacc_declare_link:1;
/* This is an OpenACC acclerator function at level N - 1 */
- unsigned oacc_function:3;
+ ENUM_BITFIELD (oacc_function) oacc_function:3;
It's probably not huge, but I noticed that some other enum bitfields are
declared that way.
> btw.. the OACC merge from the gomp4 branch added a copy'n paste error
> in an error message. May i ask you to regtest and install the below:
>
> diff --git a/gcc/fortran/openmp.c b/gcc/fortran/openmp.c
> index fcfe671be8b..ac1f4fc7619 100644
> --- a/gcc/fortran/openmp.c
> +++ b/gcc/fortran/openmp.c
> @@ -5848,13 +5848,13 @@ resolve_oacc_loop_blocks (gfc_code *code)
> if (c->code->ext.omp_clauses->worker)
> gfc_error ("Loop parallelized across gangs is not
> allowed " "inside loop parallelized across workers at %L",
> &code->loc);
> if (c->code->ext.omp_clauses->vector)
> gfc_error ("Loop parallelized across gangs is not
> allowed "
> - "inside loop parallelized across workers
> at %L",
> + "inside loop parallelized across vectors
> at %L", &code->loc);
> }
> if (code->ext.omp_clauses->worker)
> {
> if (c->code->ext.omp_clauses->worker)
> gfc_error ("Loop parallelized across workers is not
> allowed "
Sure. That looks reasonable. I'll also update and/or add new tests as
necessary.
Thanks for the review. I have couple in my queue already, but I hope to
have both my updated patch and your patch ready early next week. This
week I've been preparing a bunch of miscellaneous OpenACC patches, but
next week return to OpenACC routine patches. In terms of Fortran, I have
a patch that introduces support for the nohost routine clause (and the
bind clause, but bind hasn't been implemented in the middle end yet, so
I won't include it), as well as a patch the aforementioned routine
support in Fortran modules.
Cesar
next prev parent reply other threads:[~2018-09-20 14:41 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-05 19:52 Cesar Philippidis
2018-09-19 22:30 ` Bernhard Reutner-Fischer
2018-09-20 14:41 ` Cesar Philippidis [this message]
2018-09-20 16:20 ` Bernhard Reutner-Fischer
2018-09-24 14:49 ` Cesar Philippidis
2018-09-25 7:08 ` Bernhard Reutner-Fischer
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=ed6258d2-d706-94db-77d8-500e2fe45f9b@codesourcery.com \
--to=cesar@codesourcery.com \
--cc=fortran@gcc.gnu.org \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--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).