Re: [PATCH 6/7] openmp, fortran: Add Fortran support for parsing metadirectives
This patch (again, to be applied on top of the current set of metadirective patches) fixes two minor issues with metadirectives in the Fortran front-end. - 'sorry' is called if a declarative OpenMP directive is found in a metadirective clause. - An ICE that occurs with an empty metadirective (i.e. just '!$omp metadirective' with nothing else) is fixed. Thanks KwokFrom 153b8dbd19cf90b1869be7f409d55d1ab5ba81d5 Mon Sep 17 00:00:00 2001 From: Kwok Cheung Yeung Date: Fri, 11 Feb 2022 15:42:50 + Subject: [PATCH 2/2] openmp: More Fortran front-end fixes for metadirectives This adds a check for declarative OpenMP directives in metadirective variants (already present in the C/C++ front-ends), and fixes an ICE when an empty metadirective (i.e. just '!$omp metadirective') is presented. 2022-02-11 Kwok Cheung Yeung gcc/fortran/ * gfortran.h (is_omp_declarative_stmt): New. * openmp.cc (match_omp_metadirective): Reject declarative OpenMP directives with 'sorry'. * parse.cc (parse_omp_metadirective_body): Check that state stack head is non-null before dereferencing. (is_omp_declarative_stmt): New. gcc/testsuite/ * gfortran.dg/gomp/metadirective-2.f90 (main): Test empty metadirective. --- gcc/fortran/gfortran.h | 1 + gcc/fortran/openmp.cc| 3 +++ gcc/fortran/parse.cc | 16 +++- .../gfortran.dg/gomp/metadirective-2.f90 | 5 - 4 files changed, 23 insertions(+), 2 deletions(-) diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index bdb4b0f6aa5..37eb039b6d4 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -3852,6 +3852,7 @@ bool gfc_parse_file (void); void gfc_global_used (gfc_gsymbol *, locus *); gfc_namespace* gfc_build_block_ns (gfc_namespace *); gfc_statement match_omp_directive (void); +bool is_omp_declarative_stmt (gfc_statement); /* dependency.cc */ int gfc_dep_compare_functions (gfc_expr *, gfc_expr *, bool); diff --git a/gcc/fortran/openmp.cc b/gcc/fortran/openmp.cc index 5e87e18ce0d..0071484817d 100644 --- a/gcc/fortran/openmp.cc +++ b/gcc/fortran/openmp.cc @@ -5151,6 +5151,9 @@ match_omp_metadirective (bool begin_p) gfc_statement directive = match_omp_directive (); gfc_matching_omp_context_selector = false; + if (is_omp_declarative_stmt (directive)) + sorry ("declarative directive variants are not supported"); + if (gfc_error_flag_test ()) { gfc_current_locus = old_loc; diff --git a/gcc/fortran/parse.cc b/gcc/fortran/parse.cc index cd18315697e..cb8acb3c68f 100644 --- a/gcc/fortran/parse.cc +++ b/gcc/fortran/parse.cc @@ -5841,7 +5841,8 @@ parse_omp_metadirective_body (gfc_statement omp_st) gfc_in_metadirective_body = old_in_metadirective_body; - *clause->code = *gfc_state_stack->head; + if (gfc_state_stack->head) + *clause->code = *gfc_state_stack->head; pop_state (); gfc_commit_symbols (); @@ -7081,3 +7082,16 @@ is_oacc (gfc_state_data *sd) return false; } } + +/* Return true if ST is a declarative OpenMP statement. */ +bool +is_omp_declarative_stmt (gfc_statement st) +{ + switch (st) +{ + case_omp_decl: + return true; + default: + return false; +} +} diff --git a/gcc/testsuite/gfortran.dg/gomp/metadirective-2.f90 b/gcc/testsuite/gfortran.dg/gomp/metadirective-2.f90 index 06c324589d0..cdd5e85068e 100644 --- a/gcc/testsuite/gfortran.dg/gomp/metadirective-2.f90 +++ b/gcc/testsuite/gfortran.dg/gomp/metadirective-2.f90 @@ -43,7 +43,7 @@ program main end do !$omp end metadirective - ! Test labels in the body + ! Test labels in the body. !$omp begin metadirective & !$omp& when (device={arch("nvptx")}: parallel do) & !$omp& when (device={arch("gcn")}: parallel) @@ -56,4 +56,7 @@ program main 20continue end do !$omp end metadirective + + ! Test empty metadirective. + !$omp metadirective end program -- 2.25.1
Re: [PATCH 6/7] openmp, fortran: Add Fortran support for parsing metadirectives
> This patch implements metadirective parsing in the Fortran frontend. This patch (to be applied on top of the current set of metadirective patches) implements a feature that was present in the C and C++ front-ends but not in Fortran - the early culling of metadirective variants that can be eliminated during parsing because their selectors are resolvable at parse-time and still do not match. This is more efficient, and allows code with nested metadirectives like this (which works on other compilers) to compile: !$omp metadirective when (implementation={vendor("ibm")}: & !$omp& target teams distribute) !$omp metadirective when (implementation={vendor("gnu")}: parallel do) This would currently fail because when parsing the body of the 'target teams distribute', the parser sees the metadirective when it is expecting a loop nest. If the vendor("ibm") is eliminated early though, it would just evaluate to '!$omp nothing' and the following metadirective would not be incorrect. This doesn't work for selectors such as 'arch' that would need to be deferred until later passes though. As the selector matching code (omp_context_selector_matches in omp-general.cc) works on Generic trees, I have allowed for a limited translation from the GFortran AST form to tree form during parsing, skipping over things like expression translation that must be done later. I have also fixed another FE issue with nested metadirectives, that occurs when you have something like: program P !$omp metadirective !$omp metadirective !$omp metadirective end program P When gfc_match_end is called after parsing the do statement, it needs to drop down multiple levels from the innermost metadirective state to that of 'program P' in order to find the proper end type, and not just one level as it currently does. Thanks KwokFrom 5a7b109a014422a5b43e43669df1dc0d59e830cf Mon Sep 17 00:00:00 2001 From: Kwok Cheung Yeung Date: Fri, 11 Feb 2022 11:20:18 + Subject: [PATCH 1/2] openmp: Eliminate non-matching metadirective variants early in Fortran front-end This patch checks during parsing if a metadirective selector is both resolvable and non-matching - if so, it is removed from further consideration. This is both more efficient, and avoids spurious syntax errors caused by considering combinations of selectors that lead to invalid combinations of OpenMP directives, when that combination would never arise in the first place. This exposes another bug - when metadirectives that are not of the begin-end variety are nested, we might have to drill up through multiple layers of the state stack to reach the state for the next statement. This is now fixed. 2022-02-11 Kwok Cheung Yeung gcc/ * omp-general.cc (DELAY_METADIRECTIVES_AFTER_LTO): Check that cfun is non-null before derefencing. gcc/fortran/ * decl.cc (gfc_match_end): Search for first previous state that is not COMP_OMP_METADIRECTIVE. * gfortran.h (gfc_skip_omp_metadirective_clause): Add prototype. * openmp.cc (match_omp_metadirective): Skip clause if result of gfc_skip_omp_metadirective_clause is true. * trans-openmp.cc (gfc_trans_omp_set_selector): Add argument and disable expression conversion if false. (gfc_skip_omp_metadirective_clause): New. gcc/testsuite/ * gfortran.dg/gomp/metadirective-8.f90: New. --- gcc/fortran/decl.cc | 21 +- gcc/fortran/gfortran.h| 4 ++ gcc/fortran/openmp.cc | 7 +++- gcc/fortran/trans-openmp.cc | 38 ++- gcc/omp-general.cc| 5 ++- .../gfortran.dg/gomp/metadirective-8.f90 | 22 +++ 6 files changed, 81 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gfortran.dg/gomp/metadirective-8.f90 diff --git a/gcc/fortran/decl.cc b/gcc/fortran/decl.cc index e024e360c88..a77ac768175 100644 --- a/gcc/fortran/decl.cc +++ b/gcc/fortran/decl.cc @@ -8325,15 +8325,32 @@ gfc_match_end (gfc_statement *st) case COMP_CONTAINS: case COMP_DERIVED_CONTAINS: -case COMP_OMP_METADIRECTIVE: case COMP_OMP_BEGIN_METADIRECTIVE: state = gfc_state_stack->previous->state; block_name = gfc_state_stack->previous->sym == NULL -? NULL : gfc_state_stack->previous->sym->name; + ? NULL : gfc_state_stack->previous->sym->name; abreviated_modproc_decl = gfc_state_stack->previous->sym && gfc_state_stack->previous->sym->abr_modproc_decl; break; +case COMP_OMP_METADIRECTIVE: + { + /* Metadirectives can be nested, so we need to drill down to the + first state that is not COMP_OMP_METADIRECTIVE. */ + gfc_state_data *state_data = gfc_state_stack; + + do + { + state_data = state_data->previous; + state =
[PATCH 6/7] openmp, fortran: Add Fortran support for parsing metadirectives
This patch implements metadirective parsing in the Fortran frontend. The code previously used to process context selectors in 'declare variant' is refactored so that it can be reused in metadirectives. The big case lists in parse_executable are moved into macros, since parse_omp_metadirective_body needs to know how to act depending on the type of directive variant. The selection of end statements in parse_omp_do and parse_omp_structured_block are also delegated to gfc_omp_end_stmt. Labels in directive variant bodies are handled by assigning a unique number to each statement body parsed in a metadirective, and adding this number as a field to gfc_st_label, such that labels with identical numbers but different region ids are considered different. I have also reverted my previous changes to the TREE_STRING_LENGTH check in omp_check_context_selector and omp_context_name_list_prop. This is because in the accel compiler, lang_GNU_Fortran returns 0 even when the code is in Fortran, resulting in the selector failing to match. Instead, I opted to increment the TREE_STRING_LENGTH when it is created in gfc_trans_omp_set_selector - this should be safe as it is an internal implementation detail not visible to end users. KwokFrom eed8a06fca397edd5fb451f08c8b1a6f7d67951a Mon Sep 17 00:00:00 2001 From: Kwok Cheung Yeung Date: Mon, 6 Dec 2021 22:59:36 + Subject: [PATCH 6/7] openmp, fortran: Add Fortran support for parsing metadirectives This adds support for parsing OpenMP metadirectives in the Fortran front end. 2021-12-10 Kwok Cheung Yeung gcc/ * omp-general.c (omp_check_context_selector): Revert string length check. (omp_context_name_list_prop): Likewise. gcc/fortran/ * decl.c (gfc_match_end): Handle COMP_OMP_METADIRECTIVE and COMP_OMP_BEGIN_METADIRECTIVE. * dump-parse-tree.c (show_omp_node): Handle EXEC_OMP_METADIRECTIVE. (show_code_node): Handle EXEC_OMP_METADIRECTIVE. * gfortran.h (enum gfc_statement): Add ST_OMP_METADIRECTIVE, ST_OMP_BEGIN_METADIRECTIVE and ST_OMP_END_METADIRECTIVE. (struct gfc_omp_metadirective_clause): New structure. (gfc_get_omp_metadirective_clause): New macro. (struct gfc_st_label): Add omp_region field. (enum gfc_exec_op): Add EXEC_OMP_METADIRECTIVE. (struct gfc_code): Add omp_metadirective_clauses field. (gfc_free_omp_metadirective_clauses): New prototype. (match_omp_directive): New prototype. * io.c (format_asterisk): Initialize omp_region field. * match.h (gfc_match_omp_begin_metadirective): New prototype. (gfc_match_omp_metadirective): New prototype. * openmp.c (gfc_match_omp_eos): Match ')' in context selectors. (gfc_free_omp_metadirective_clauses): New. (gfc_match_omp_clauses): Remove context_selector argument. Rely on gfc_match_omp_eos to match end of clauses. (match_omp): Remove extra argument to gfc_match_omp_clauses. (gfc_match_omp_context_selector): Remove extra argument to gfc_match_omp_clauses. Set gfc_matching_omp_context_selector before call to gfc_match_omp_clauses and reset after. (gfc_match_omp_context_selector_specification): Modify to take a gfc_omp_set_selector** argument. (gfc_match_omp_declare_variant): Pass set_selectors to gfc_match_omp_context_selector_specification. (match_omp_metadirective): New. (gfc_match_omp_begin_metadirective): New. (gfc_match_omp_metadirective): New. (resolve_omp_metadirective): New. (gfc_resolve_omp_directive): Handle EXEC_OMP_METADIRECTIVE. * parse.c (gfc_matching_omp_context_selector): New variable. (gfc_in_metadirective_body): New variable. (gfc_omp_region_count): New variable. (decode_omp_directive): Match 'begin metadirective', 'end metadirective' and 'metadirective'. (match_omp_directive): New. (case_omp_structured_block): New. (case_omp_do): New. (gfc_ascii_statement): Handle metadirective statements. (gfc_omp_end_stmt): New. (parse_omp_do): Delegate to gfc_omp_end_stmt. (parse_omp_structured_block): Delegate to gfc_omp_end_stmt. Handle ST_OMP_END_METADIRECTIVE. (parse_omp_metadirective_body): New. (parse_executable): Delegate to case_omp_structured_block and case_omp_do. Return after one statement if compiling regular metadirective. Handle metadirective statements. (gfc_parse_file): Reset gfc_omp_region_count, gfc_in_metadirective_body and gfc_matching_omp_context_selector. * parse.h (enum gfc_compile_state): Add COMP_OMP_METADIRECTIVE and COMP_OMP_BEGIN_METADIRECTIVE. (gfc_omp_end_stmt): New prototype. (gfc_matching_omp_context_selector): New declaration. (gfc_in_metadirective_body): New declaration