Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
Hi Tobias! On 20.02.2014 03:51, Tobias Burnus wrote: On 10.02.2014 02:22, Tobias Burnus wrote: a) Does this part work well when both -fopenmp and -fopenacc is used? I mean: !$acc loop followed/preceded by !$omp do? I could imagine that there could be clashes, especially when - e.g. - collapse doesn't match. PGI: Silently ignores OpenMP pragmas. CAPS: Ignored option '--define' (_OPENMP=). I like how Cray handles it: It permits both - but neither OpenMP - OpenACC nesting nor vice versa. (It might not always detectable.) ERROR: The !$OMP PARALLEL DO directive cannot be specified within a !$ACC PARALLEL region. And adding OpenACC to an OpenMP loop fails with: ERROR: The !$ACC LOOP directive cannot be specified within a !$OMP PARALLEL DO region. (One gets the same error independent whether one tries to place the pragma on the same loop or just nested in the parallel pragma or on different loops.) I think doing likewise would be best. I agree. + if (gfc_implicit_pure (NULL)) +gfc_current_ns-proc_name-attr.implicit_pure = 0; I believe that will fail with BLOCK - cf. gfc_implicit_pure() Fortunally, it doesn't. Are you sure that it works? A block starts a new namespace, hence, gfc_implicit_pure() does: After your notice about namespaces, I tested !$acc declare attribute. Viola, it fails. However, other directives work. Side question: Do we also need to unset implicit_pure for OpenMP? As you can see in decode_omp_directive function, the flag is already unset. -- Ilmir.
Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
Hi Tobias! Thanks a lot for your review! I have tested your notes on two compilers which support OpenACC: PGI 14.1 and CAPS 3.4.1. If I made a mistake and you've collected results which differ from mine (whether you compiler is one of the above or not), please, let me know. Unfortunally, neither PGI nor CAPS don't support Fortran 2008. These are results: On 10.02.2014 02:22, Tobias Burnus wrote: a) Does this part work well when both -fopenmp and -fopenacc is used? I mean: !$acc loop followed/preceded by !$omp do? I could imagine that there could be clashes, especially when - e.g. - collapse doesn't match. PGI: Silently ignores OpenMP pragmas. CAPS: Ignored option '--define' (_OPENMP=). b) Do you also handle DO CONCURRENT - either by rejecting it or by accepting it? Namely, !$acc loop do concurrent(i=1:5) end do !$acc end loop end Side remark, with -fopenmp, it does ICE: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60127 My implemetation also fails, will fix. By the way, should we support these loops? I think we should, since DO CONCURRENT loops are parallelizable. Talking about !$acc loop: I vaguely remember that OpenACC 1.0's spec doesn't have !$acc end loop while I have seen OpenACC programs which use it. How do you handle !$acc end loop? Looking at parse.c, it seems to simply error out. I wonder whether one should be a bit more graceful. For instance, the following examples use !$acc end loop: http://devblogs.nvidia.com/parallelforall/openacc-example-part-2/ [If I remember correctly, pgf95 and Cray ftn silently accepts end loop while pathf95 accepts it with a warning.] And looking at the spec of OpenACC 1.0 and 2.0a, the end loop seems to be invalid. How about following PathScale's ENZO and accepting end loop with a warning? Or at least error out with a good error message. No, the spec doesn't specify !$acc end loop. However, compilers handle this construction differently: PGI: silently accepts. CAPS: Syntax error: expecting ('parallel' ('loop' or end)) or (('kernels' or 'dfkernels') ('loop' or end)) or 'data' or 'host_data' !$acc end loop My implementation also errors out, but I agree, we should accept this with warning. + if (gfc_pure (NULL)) +{ + gfc_error_now (OpenACC directives at %C may not appear in PURE + or ELEMENTAL procedures); Using gfc_pure() you do not check for ELEMENTAL: Since Fortran 2008, there are also IMPURE ELEMENTAL procedures. I don't know the spec, but I don't really see a reason why OpenACC shouldn't be permitted in IMPURE ELEMENTAL procedures. (BTW: ELEMENTAL implies PURE unless an explicit IMPURE is used.) In any case, either drop or ELEMENTAL or also check for the elemental attribute. I think I should drop or ELEMENTAL since OpenMP also accepts directives in IMPURE ELEMENTAL procecdures. + if (gfc_implicit_pure (NULL)) +gfc_current_ns-proc_name-attr.implicit_pure = 0; I believe that will fail with BLOCK - cf. gfc_implicit_pure() real function foo(n) integer, value :: n BLOCK integer i real sum !$acc loop reduce(+:sum) do i=1, n sum += sin(real(i)) end do END BLOCK end Fortunally, it doesn't. -- Ilmir.
Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
Hi Ilmir, thanks for your reply; I am looking forward to your updated patch. Ilmir Usmanov wrote: I have tested your notes on two compilers which support OpenACC: PGI 14.1 and CAPS 3.4.1. I can add Cray ftn results, if you want me to cross-check something. On 10.02.2014 02:22, Tobias Burnus wrote: a) Does this part work well when both -fopenmp and -fopenacc is used? I mean: !$acc loop followed/preceded by !$omp do? I could imagine that there could be clashes, especially when - e.g. - collapse doesn't match. PGI: Silently ignores OpenMP pragmas. CAPS: Ignored option '--define' (_OPENMP=). I like how Cray handles it: It permits both - but neither OpenMP - OpenACC nesting nor vice versa. (It might not always detectable.) ERROR: The !$OMP PARALLEL DO directive cannot be specified within a !$ACC PARALLEL region. And adding OpenACC to an OpenMP loop fails with: ERROR: The !$ACC LOOP directive cannot be specified within a !$OMP PARALLEL DO region. (One gets the same error independent whether one tries to place the pragma on the same loop or just nested in the parallel pragma or on different loops.) I think doing likewise would be best. A simpler approach is to reject using -fopenmp and -fopenacc simultaneously. b) Do you also handle DO CONCURRENT - either by rejecting it or by accepting it? Namely, !$acc loop do concurrent(i=1:5) end do !$acc end loop end Side remark, with -fopenmp, it does ICE: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60127 My implemetation also fails, will fix. By the way, should we support these loops? I think we should, since DO CONCURRENT loops are parallelizable. I think one should at least error out and not ICE. The long-term solution should be to support DO CONCURRENT with both OpenMP and OpenACC; although one option would be to wait until the specs officially support it. If you want to support it, please recall that do concurrent also permits a mask argument, which makes everything a bit more complicated. (Cf. gcc/fortran/trans-stmt.c's gfc_trans_forall_1 function.) No, the spec doesn't specify !$acc end loop. However, compilers handle this construction differently: PGI: silently accepts. Which is not surprising given that NVidia's and PGI's example often use !$acc end loop. [Cray ftn also accepts it silently.] + if (gfc_pure (NULL)) +{ + gfc_error_now (OpenACC directives at %C may not appear in PURE + or ELEMENTAL procedures); ... In any case, either drop or ELEMENTAL or also check for the elemental attribute. I think I should drop or ELEMENTAL since OpenMP also accepts directives in IMPURE ELEMENTAL procecdures. Fine with me. + if (gfc_implicit_pure (NULL)) +gfc_current_ns-proc_name-attr.implicit_pure = 0; I believe that will fail with BLOCK - cf. gfc_implicit_pure() Fortunally, it doesn't. Are you sure that it works? A block starts a new namespace, hence, gfc_implicit_pure() does: --cut--- /* Check if the current procedure is implicit_pure. Walk up the procedure list until we find a procedure. */ for (ns = gfc_current_ns; ns; ns = ns-parent) { sym = ns-proc_name; if (sym == NULL) return 0; if (sym-attr.flavor == FL_PROCEDURE) break; } } return sym-attr.flavor == FL_PROCEDURE sym-attr.implicit_pure !sym-attr.pure; --cut--- But you set gfc_current_ns-proc_name-attr.implicit_pure = 0. If gfc_current_ns is the BLOCK, the procedure might still have the implict_pure attribute set. Side question: Do we also need to unset implicit_pure for OpenMP? Tobias
Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
Ilmir Usmanov wrote: OpenACC 1.0 support to fortran FE -- core. --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -1031,9 +1031,22 @@ show_omp_node (int level, gfc_code *c) { gfc_omp_clauses *omp_clauses = NULL; const char *name = NULL; + bool is_oacc = false; I'd also update the comment before the function and mention OpenACC there. It currently reads: /* Show a single OpenMP directive node and everything underneath it if necessary. */ + fprintf (dumpfile, !$%s %s, is_oacc?ACC:OMP, name); Add spaces around ? and : @@ -1215,7 +1334,7 @@ show_omp_node (int level, gfc_code *c) - fprintf (dumpfile, !$OMP END %s, name); + fprintf (dumpfile, !$%s END %s, is_oacc?ACC:OMP, name); Ditto. --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h +/* Likewise to gfc_namelist, but contains expressions. */ +typedef struct gfc_exprlist +{ + struct gfc_expr *expr; + struct gfc_exprlist *next; +} +gfc_exprlist; I don't feel strong about it, but I think it is more GCC / gfortran style to use gfc_expr_list instead of gfc_exprlist. + /* OpenACC. */ + struct gfc_expr *async_expr; + struct gfc_expr *gang_expr; + struct gfc_expr *worker_expr; + struct gfc_expr *vector_expr; + struct gfc_expr *num_gangs_expr; + struct gfc_expr *num_workers_expr; + struct gfc_expr *vector_length_expr; + struct gfc_expr *non_clause_wait_expr; + gfc_exprlist *waitlist; + gfc_exprlist *tilelist; + bool async, gang, worker, vector, seq, independent; + bool wait, par_auto, gang_static; I wonder whether it would make sense to use bit fields here. --- a/gcc/fortran/match.c +++ b/gcc/fortran/match.c @@ -2595,6 +2595,33 @@ match_exit_cycle (gfc_statement st, gfc_exec_op op) if (cnt 0 o != NULL o-state == COMP_OMP_STRUCTURED_BLOCK + (o-head-op == EXEC_OACC_LOOP + || o-head-op == EXEC_OACC_PARALLEL_LOOP)) +{ + int collapse = 1; + gcc_assert (o-head-next != NULL + (o-head-next-op == EXEC_DO + || o-head-next-op == EXEC_DO_WHILE) Two questions: a) Does this part work well when both -fopenmp and -fopenacc is used? I mean: !$acc loop followed/preceded by !$omp do? I could imagine that there could be clashes, especially when - e.g. - collapse doesn't match. b) Do you also handle DO CONCURRENT - either by rejecting it or by accepting it? Namely, !$acc loop do concurrent(i=1:5) end do !$acc end loop end Side remark, with -fopenmp, it does ICE: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60127 Talking about !$acc loop: I vaguely remember that OpenACC 1.0's spec doesn't have !$acc end loop while I have seen OpenACC programs which use it. How do you handle !$acc end loop? Looking at parse.c, it seems to simply error out. I wonder whether one should be a bit more graceful. For instance, the following examples use !$acc end loop: http://devblogs.nvidia.com/parallelforall/openacc-example-part-2/ [If I remember correctly, pgf95 and Cray ftn silently accepts end loop while pathf95 accepts it with a warning.] And looking at the spec of OpenACC 1.0 and 2.0a, the end loop seems to be invalid. How about following PathScale's ENZO and accepting end loop with a warning? Or at least error out with a good error message. + if (st == ST_EXIT cnt = collapse) +{ + gfc_error (EXIT statement at %C terminating !$ACC LOOP loop); + return MATCH_ERROR; +} + if (st == ST_CYCLE cnt collapse) +{ + gfc_error (CYCLE statement at %C to non-innermost collapsed + !$ACC LOOP loop); + return MATCH_ERROR; +} +} I wonder whether one should include for OpenMP and OpenACC some additional checks as done for DO CONCURRENT or whether those aren't required. I think image controll statements like Fortran 2008's CRITICAL block might cause problems with OpenACC/OpenMP concurrency. (Given that OpenACC/OpenMP likely ignores Fortran 2008's coarrays, one might defer this until OpenACC/OpenMP has been updated for Fortran 2008.) + if (gfc_pure (NULL)) +{ + gfc_error_now (OpenACC directives at %C may not appear in PURE + or ELEMENTAL procedures); Using gfc_pure() you do not check for ELEMENTAL: Since Fortran 2008, there are also IMPURE ELEMENTAL procedures. I don't know the spec, but I don't really see a reason why OpenACC shouldn't be permitted in IMPURE ELEMENTAL procedures. (BTW: ELEMENTAL implies PURE unless an explicit IMPURE is used.) In any case, either drop or ELEMENTAL or also check for the elemental attribute. + if (gfc_implicit_pure (NULL)) +gfc_current_ns-proc_name-attr.implicit_pure = 0; I believe that will fail with BLOCK - cf. gfc_implicit_pure() real function foo(n) integer, value :: n BLOCK integer i real sum !$acc loop reduce(+:sum) do i=1, n sum += sin(real(i)) end do END BLOCK end
Re: [PING] [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
Hi Jakub! On 31.01.2014 15:45, Ilmir Usmanov wrote: Hi Jakub! Thank you for review and quick answer. The above are OpenACC specific clauses, so they should have OACC_LIST_*? I just followed Thomas's style recomendations: If we're adding new names for implementing OpenACC things, maybe we should also name these OMP_*, to keep things simple to read in the code that uses them. And I agree with him. + case OMP_LIST_DEVICE: type = DEVICE; break; This one is in OpenMP 4.0 too (though, I didn't get to OpenMP 4.0 / fortran support yet), so this should be OMP_LIST_DEVICE. As far as I know, OpenMP device clause requires integer-expression, not variable-list, so, I think, we can use OMP_LIST_DEVICE to represent OpenACC device clause. So, what should I do? Is current naming OK? Or you think it's better to use OACC_ prefix for OpenACC specific stuff in Fortran front-end and OMP_ prefix in middle-end? -- Ilmir.
Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
OpenACC 1.0 support to fortran FE -- core. gcc/fortran/ * dump-parse-tree.c (show_omp_node): Dump also OpenACC executable statements. (show_code_node): Call it. * gfortran.h (ST_OACC_PARALLEL_LOOP, ST_OACC_END_PARALLEL_LOOP, ST_OACC_PARALLEL, ST_OACC_END_PARALLEL, ST_OACC_KERNELS, ST_OACC_END_KERNELS, ST_OACC_DATA, ST_OACC_END_DATA, ST_OACC_HOST_DATA, ST_OACC_END_HOST_DATA, ST_OACC_LOOP, ST_OACC_DECLARE, ST_OACC_UPDATE, ST_OACC_WAIT, ST_OACC_CACHE, ST_OACC_KERNELS_LOOP, ST_OACC_END_KERNELS_LOOP, ST_OACC_ENTER_DATA, ST_OACC_EXIT_DATA): New statements. (gfc_exprlist): New structure to hold list of expressions. (OMP_LIST_COPY, OMP_LIST_DATA_CLAUSE_FIRST, OMP_LIST_OACC_COPYIN, OMP_LIST_COPYOUT, OMP_LIST_CREATE, OMP_LIST_DELETE, OMP_LIST_PRESENT, OMP_LIST_PRESENT_OR_COPY, OMP_LIST_PRESENT_OR_COPYIN, OMP_LIST_PRESENT_OR_COPYOUT, OMP_LIST_PRESENT_OR_CREATE, OMP_LIST_DEVICEPTR, OMP_LIST_DATA_CLAUSE_LAST, OMP_LIST_USE_DEVICE, OMP_LIST_DEVICE_RESIDENT, OMP_LIST_HOST, OMP_LIST_DEVICE, OMP_LIST_CACHE): New types of list, allowed in clauses. (gfc_omp_clauses): Add OpenACC clauses. (gfc_namespace): Add OpenACC declare directive clauses. (EXEC_OACC_KERNELS_LOOP, EXEC_OACC_PARALLEL_LOOP, EXEC_OACC_PARALLEL, EXEC_OACC_KERNELS, EXEC_OACC_DATA, EXEC_OACC_HOST_DATA, EXEC_OACC_LOOP, EXEC_OACC_UPDATE, EXEC_OACC_WAIT, EXEC_OACC_CACHE, EXEC_OACC_ENTER_DATA, EXEC_OACC_EXIT_DATA): New executable statements. (gfc_free_exprlist): New function declaration. (gfc_resolve_oacc_directive): Likewise. (gfc_resolve_oacc_parallel_loop_blocks): Likewise. (gfc_resolve_oacc_blocks): Likewise. * match.c (match_exit_cycle): Add support of OpenACC regions and loops. * match.h (gfc_match_oacc_cache): New function declaration. (gfc_match_oacc_wait, gfc_match_oacc_update): Likewise. (gfc_match_oacc_declare, gfc_match_oacc_loop): Likewise. (gfc_match_oacc_host_data, gfc_match_oacc_data): Likewise. (gfc_match_oacc_kernels, gfc_match_oacc_kernels_loop): Likewise. (gfc_match_oacc_parallel, gfc_match_oacc_parallel_loop): Likewise. (gfc_match_oacc_enter_data, gfc_match_oacc_exit_data): Likewise. * parse.c (decode_oacc_directive): New function. (verify_token_free, verify_token_fixed): New helper functions. (next_free, next_fixed): Decode !$ACC sentinel. (case_executable): Add ST_OACC_UPDATE, ST_OACC_WAIT, ST_OACC_CACHE, ST_OACC_ENTER_DATA and ST_OACC_EXIT_DATA directives. (case_exec_markers): Add ST_OACC_PARALLEL_LOOP, ST_OACC_PARALLEL, ST_OACC_KERNELS, ST_OACC_DATA, ST_OACC_HOST_DATA, ST_OACC_LOOP and ST_OACC_KERNELS_LOOP directives. (push_state): Initialize OpenACC declare clauses. (gfc_ascii_statement): Dump names of OpenACC directives. (verify_st_order): Verify OpenACC declare directive as declarative. (parse_spec): Push clauses to state stack when declare directive is parsed. (parse_oacc_structured_block, parse_oacc_loop): New functions. (parse_executable): Call them. (parse_progunit): Move declare clauses from state stack to namespace. * parse.h (gfc_state_data): Add declare directive's clauses. * resolve.c (gfc_resolve_blocks): Resolve OpenACC directives. (resolve_code): Likewise. * scanner.c (openacc_flag, openacc_locus): New static variables. (skip_oacc_attribute, skip_omp_attribute): New helper functions. (skip_free_comments, skip_fixed_comments): Don't skip !$ACC sentinel. (gfc_next_char_literal): Support OpenACC directives. * st.c (gfc_free_statement): Free also OpenACC directives. From f8f10537d2555e596bdd1655990150d45ef08f9b Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov i.usma...@samsung.com Date: Fri, 31 Jan 2014 13:25:42 +0400 Subject: [PATCH 1/6] OpenACC fortran front-end -- part 1 --- gcc/fortran/dump-parse-tree.c | 135 +- gcc/fortran/gfortran.h| 59 ++ gcc/fortran/match.c | 27 +++ gcc/fortran/match.h | 15 ++ gcc/fortran/parse.c | 425 ++ gcc/fortran/parse.h | 1 + gcc/fortran/resolve.c | 36 gcc/fortran/scanner.c | 376 ++--- gcc/fortran/st.c | 12 ++ 9 files changed, 980 insertions(+), 106 deletions(-) diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c index b1343bc..9ef9db4 100644 --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -1031,9 +1031,22 @@ show_omp_node (int level, gfc_code *c) { gfc_omp_clauses *omp_clauses = NULL; const char *name = NULL; + bool is_oacc = false; switch (c-op) { +case EXEC_OACC_PARALLEL_LOOP: name = PARALLEL LOOP; is_oacc = true; break; +case EXEC_OACC_PARALLEL: name = PARALLEL; is_oacc = true; break; +case EXEC_OACC_KERNELS_LOOP: name = KERNELS LOOP; is_oacc = true; break; +case
Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
On Fri, Jan 31, 2014 at 03:10:59PM +0400, Ilmir Usmanov wrote: @@ -1182,6 +1281,26 @@ show_omp_node (int level, gfc_code *c) { switch (list_type) { + case OMP_LIST_COPY: type = COPY; break; + case OMP_LIST_OACC_COPYIN: type = COPYIN; break; + case OMP_LIST_COPYOUT: type = COPYOUT; break; + case OMP_LIST_CREATE: type = CREATE; break; + case OMP_LIST_DELETE: type = DELETE; break; + case OMP_LIST_PRESENT: type = PRESENT; break; + case OMP_LIST_PRESENT_OR_COPY: +type = PRESENT_OR_COPY; break; + case OMP_LIST_PRESENT_OR_COPYIN: +type = PRESENT_OR_COPYIN; break; + case OMP_LIST_PRESENT_OR_COPYOUT: +type = PRESENT_OR_COPYOUT; break; + case OMP_LIST_PRESENT_OR_CREATE: +type = PRESENT_OR_CREATE; break; + case OMP_LIST_DEVICEPTR: type = DEVICEPTR; break; + case OMP_LIST_USE_DEVICE: type = USE_DEVICE; break; + case OMP_LIST_DEVICE_RESIDENT: type = USE_DEVICE; break; + case OMP_LIST_HOST: type = HOST; break; The above are OpenACC specific clauses, so they should have OACC_LIST_*? + case OMP_LIST_DEVICE: type = DEVICE; break; This one is in OpenMP 4.0 too (though, I didn't get to OpenMP 4.0 / fortran support yet), so this should be OMP_LIST_DEVICE. + case OMP_LIST_CACHE: type = ; break; Again, this is OpenACC specific. Jakub
Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
Hi Jakub! Thank you for review and quick answer. The above are OpenACC specific clauses, so they should have OACC_LIST_*? I just followed Thomas's style recomendations: If we're adding new names for implementing OpenACC things, maybe we should also name these OMP_*, to keep things simple to read in the code that uses them. And I agree with him. + case OMP_LIST_DEVICE: type = DEVICE; break; This one is in OpenMP 4.0 too (though, I didn't get to OpenMP 4.0 / fortran support yet), so this should be OMP_LIST_DEVICE. As far as I know, OpenMP device clause requires integer-expression, not variable-list, so, I think, we can use OMP_LIST_DEVICE to represent OpenACC device clause. -- Thanks, Ilmir.
Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
Hi, Thomas Schwinge wrote: Regarding my comments, please keep in mind that I don't have a lot of Fortran experience; neither as a user nor as an implementor How about CC-ing fortran@gcc for Fortran patches - it increases the chance that some Fortran maintainer will give some comment on them. (When doing so, please add a line or so stating that it is for the branch and what is OpenACC - it makes it easier for those who haven't followed gcc-patches.) Tobias PS: I might look at the patches myself; however, I have a huge backlog of emails and didn't manage to do anything for GCC in the past month. Thus, don't hold your breath and count rather one some other Fortran maintainer.
Re: [PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
Hi! Regarding my comments, please keep in mind that I don't have a lot of Fortran experience; neither as a user nor as an implementor ;-) in the GCC front end, so don't hesitate to tell me if I'm misunderstanding something. As I suggested, it may make sense to CC Fortran front end maintainers for such patches. When I say again in the following, that refers to things I asked/suggested in »[PATCH 4/6] OpenACC GENERIC nodes«. On Thu, 23 Jan 2014 22:03:09 +0400, Ilmir Usmanov i.usma...@samsung.com wrote: Subject: [PATCH 1/6] OpenACC fortran FE part 1 --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -1230,6 +1230,194 @@ show_omp_node (int level, gfc_code *c) fprintf (dumpfile, (%s), c-ext.omp_name); } +/* Show a single OpenACC directive node and everything underneath it + if necessary. */ + +static void +show_oacc_node (int level, gfc_code *c) Is this something that accurately needs to reproduce valid Fortran code? Or, could we again re-use more of the existing OpenMP code, and get nearly-valid Fortran, that differs in how some of the data clauses are displayed, for example? --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -1025,16 +1031,29 @@ gfc_namelist; enum { OMP_LIST_PRIVATE, + OACC_LIST_PRIVATE = OMP_LIST_PRIVATE, OMP_LIST_FIRSTPRIVATE, + OACC_LIST_FIRSTPRIVATE = OMP_LIST_FIRSTPRIVATE, Again, possible to simply re-use the existing OMP_* ones? @@ -1047,7 +1066,29 @@ enum OMP_LIST_IOR, OMP_LIST_IEOR, OMP_LIST_REDUCTION_LAST = OMP_LIST_IEOR, - OMP_LIST_NUM + OACC_LIST_REDUCTION_LAST = OMP_LIST_REDUCTION_LAST, + OMP_LIST_NUM, + + OACC_LIST_COPY = OMP_LIST_NUM, + OACC_LIST_FIRST = OACC_LIST_COPY, + OACC_LIST_DATA_CLAUSE_FIRST = OACC_LIST_COPY, + OACC_LIST_COPYIN, + OACC_LIST_COPYOUT, + OACC_LIST_CREATE, + OACC_LIST_DELETE, + OACC_LIST_PRESENT, + OACC_LIST_PRESENT_OR_COPY, + OACC_LIST_PRESENT_OR_COPYIN, + OACC_LIST_PRESENT_OR_COPYOUT, + OACC_LIST_PRESENT_OR_CREATE, + OACC_LIST_DEVICEPTR, + OACC_LIST_DATA_CLAUSE_LAST = OACC_LIST_DEVICEPTR, + OACC_LIST_USE_DEVICE, + OACC_LIST_DEVICE_RESIDENT, + OACC_LIST_HOST, + OACC_LIST_DEVICE, + OACC_LIST_CACHE, + OACC_LIST_NUM }; Again, for conformity, maybe stick with OMP_LIST_* names (OMP_LIST_OACC_*?). Do we still need the OMP_LIST_NUM value if we now got OACC_LIST_NUM to mark the number of items, and should the latter one in fact be named OMP_LIST_NUM then?) Again, can we re-use the existing infrastructure for OpenMP's memory mapping instead of adding OACC_LIST_COPY* (and similar) here? @@ -1077,17 +1118,42 @@ typedef struct gfc_omp_clauses + /* OpenACC. */ + bool is_acc; Can we avoid the is_acc member and instead make it clear from the context whether this is OpenACC or OpenMP? (Just an idea.) + [...] } gfc_omp_clauses; #define gfc_get_omp_clauses() XCNEW (gfc_omp_clauses) +typedef gfc_omp_clauses gfc_oacc_clauses; Again, I'd just use the existing gfc_omp_* name. --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -3643,6 +3875,113 @@ parse_omp_atomic (void) } +/* Parse the statements of an OpenACC structured block. */ + +static void +parse_oacc_structured_block (gfc_statement acc_st) +{ +[...] --- a/gcc/fortran/parse.h +++ b/gcc/fortran/parse.h @@ -29,7 +29,8 @@ typedef enum COMP_BLOCK_DATA, COMP_INTERFACE, COMP_DERIVED, COMP_DERIVED_CONTAINS, COMP_BLOCK, COMP_ASSOCIATE, COMP_IF, COMP_DO, COMP_SELECT, COMP_FORALL, COMP_WHERE, COMP_CONTAINS, COMP_ENUM, - COMP_SELECT_TYPE, COMP_OMP_STRUCTURED_BLOCK, COMP_CRITICAL, COMP_DO_CONCURRENT + COMP_SELECT_TYPE, COMP_OMP_STRUCTURED_BLOCK, COMP_CRITICAL, COMP_DO_CONCURRENT, + COMP_OACC_STRUCTURED_BLOCK } gfc_compile_state; In Fortran, how is an OpenACC structured block different from an OpenMP one? In C they aren't; see the third patch in http://news.gmane.org/find-root.php?message_id=%3C87r49kuass.fsf%40kepler.schwinge.homeip.net%3E, for the C front end/middle end, which is pending approval. Or is this something else in the Fortran front end? Grüße, Thomas pgpCcAPrVfrQA.pgp Description: PGP signature
[PATCH 1/6] [GOMP4] OpenACC 1.0+ support in fortran front-end
From 84dc72f88c1b23ae995afdda0b946ebd73af102f Mon Sep 17 00:00:00 2001 From: Ilmir Usmanov i.usma...@samsung.com Date: Thu, 23 Jan 2014 21:04:37 +0400 Subject: [PATCH 1/6] OpenACC fortran FE part 1 --- gcc/fortran/decl.c| 1 + gcc/fortran/dump-parse-tree.c | 203 gcc/fortran/gfortran.h| 81 +++- gcc/fortran/match.c | 34 +++- gcc/fortran/match.h | 15 ++ gcc/fortran/parse.c | 425 ++ gcc/fortran/parse.h | 4 +- gcc/fortran/resolve.c | 36 gcc/fortran/scanner.c | 382 + gcc/fortran/st.c | 14 +- 10 files changed, 1082 insertions(+), 113 deletions(-) diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 0a0f8e0..e988983 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -6000,6 +6000,7 @@ gfc_match_end (gfc_statement *st) case COMP_CONTAINS: case COMP_DERIVED_CONTAINS: +case COMP_OACC_STRUCTURED_BLOCK: state = gfc_state_stack-previous-state; block_name = gfc_state_stack-previous-sym == NULL ? NULL : gfc_state_stack-previous-sym-name; diff --git a/gcc/fortran/dump-parse-tree.c b/gcc/fortran/dump-parse-tree.c index 14ff004..74be9ba 100644 --- a/gcc/fortran/dump-parse-tree.c +++ b/gcc/fortran/dump-parse-tree.c @@ -1230,6 +1230,194 @@ show_omp_node (int level, gfc_code *c) fprintf (dumpfile, (%s), c-ext.omp_name); } +/* Show a single OpenACC directive node and everything underneath it + if necessary. */ + +static void +show_oacc_node (int level, gfc_code *c) +{ + gfc_oacc_clauses *acc_clauses = NULL; + const char *name = NULL; + + switch (c-op) +{ +case EXEC_OACC_PARALLEL_LOOP: name = PARALLEL LOOP; break; +case EXEC_OACC_PARALLEL: name = PARALLEL; break; +case EXEC_OACC_KERNELS_LOOP: name = KERNELS LOOP; break; +case EXEC_OACC_KERNELS: name = KERNELS; break; +case EXEC_OACC_DATA: name = DATA; break; +case EXEC_OACC_HOST_DATA: name = HOST_DATA; break; +case EXEC_OACC_LOOP: name = LOOP; break; +case EXEC_OACC_UPDATE: name = UPDATE; break; +case EXEC_OACC_WAIT: name = WAIT; break; +case EXEC_OACC_CACHE: name = CACHE; break; +case EXEC_OACC_ENTER_DATA: name = ENTER DATA; break; +case EXEC_OACC_EXIT_DATA: name = EXIT DATA; break; +default: + gcc_unreachable (); +} + fprintf (dumpfile, !$ACC %s, name); + acc_clauses = c-ext.omp_clauses; + if (acc_clauses) +{ + int list; + + if (acc_clauses-if_expr) +{ + fputs ( IF(, dumpfile); + show_expr (acc_clauses-if_expr); + fputc (')', dumpfile); +} + if (acc_clauses-async) +{ + fputs ( ASYNC, dumpfile); + if (acc_clauses-async_expr) +{ + fputc ('(', dumpfile); + show_expr (acc_clauses-async_expr); + fputc (')', dumpfile); +} +} + if (acc_clauses-num_gangs_expr) +{ + fputs ( NUM_GANGS(, dumpfile); + show_expr (acc_clauses-num_gangs_expr); + fputc (')', dumpfile); +} + if (acc_clauses-num_workers_expr) +{ + fputs ( NUM_WORKERS(, dumpfile); + show_expr (acc_clauses-num_workers_expr); + fputc (')', dumpfile); +} + if (acc_clauses-vector_length_expr) +{ + fputs ( VECTOR_LENGTH(, dumpfile); + show_expr (acc_clauses-vector_length_expr); + fputc (')', dumpfile); +} + if (acc_clauses-collapse) +{ + fputs ( COLLAPSE(, dumpfile); + fprintf (dumpfile, %d, acc_clauses-collapse); + fputc (')', dumpfile); +} + if (acc_clauses-gang) +{ + fputs ( GANG, dumpfile); + if (acc_clauses-gang_expr) +{ + fputc ('(', dumpfile); + show_expr (acc_clauses-gang_expr); + fputc (')', dumpfile); +} +} + if (acc_clauses-worker) +{ + fputs ( WORKER, dumpfile); + if (acc_clauses-worker_expr) +{ + fputc ('(', dumpfile); + show_expr (acc_clauses-worker_expr); + fputc (')', dumpfile); +} +} + if (acc_clauses-vector) +{ + fputs ( VECTOR, dumpfile); + if (acc_clauses-vector_expr) +{ + fputc ('(', dumpfile); + show_expr (acc_clauses-vector_expr); + fputc (')', dumpfile); +} +} + if (acc_clauses-non_clause_wait_expr) +{ + fputc ('(', dumpfile); + show_expr (acc_clauses-non_clause_wait_expr); + fputc (')', dumpfile); +} + if (acc_clauses-seq) +fputs ( SEQ, dumpfile); + if (acc_clauses-independent) +fputs ( INDEPENDENT, dumpfile); + for (list = 0; list