diff options
author | Harald Anlauf <anlauf@gmx.de> | 2019-08-27 19:16:33 +0000 |
---|---|---|
committer | Harald Anlauf <anlauf@gcc.gnu.org> | 2019-08-27 19:16:33 +0000 |
commit | 2bd86b95f76315f102c52a81453ef375c97e8f1b (patch) | |
tree | b7b05454a14ad73627667f20119d26edd65542b7 | |
parent | 340d34bf76dd9455ab07ea849168bf2503d5edef (diff) | |
download | gcc-2bd86b95f76315f102c52a81453ef375c97e8f1b.zip gcc-2bd86b95f76315f102c52a81453ef375c97e8f1b.tar.gz gcc-2bd86b95f76315f102c52a81453ef375c97e8f1b.tar.bz2 |
re PR fortran/91496 (!GCC$ directives error if mistyped or unknown)
2019-08-27 Harald Anlauf <anlauf@gmx.de>
PR fortran/91496
* gfortran.h: Extend struct gfc_iterator for loop annotations.
* array.c (gfc_copy_iterator): Copy loop annotations by IVDEP,
VECTOR, and NOVECTOR pragmas.
* decl.c (gfc_match_gcc_ivdep, gfc_match_gcc_vector)
(gfc_match_gcc_novector): New matcher functions handling IVDEP,
VECTOR, and NOVECTOR pragmas.
* match.h: Declare prototypes of matcher functions handling IVDEP,
VECTOR, and NOVECTOR pragmas.
* parse.c (decode_gcc_attribute, parse_do_block)
(parse_executable): Decode IVDEP, VECTOR, and NOVECTOR pragmas;
emit warning for unrecognized pragmas instead of error.
* trans-stmt.c (gfc_trans_simple_do, gfc_trans_do): Add code to
emit annotations for IVDEP, VECTOR, and NOVECTOR pragmas.
* gfortran.texi: Document IVDEP, VECTOR, and NOVECTOR pragmas.
PR fortran/91496
* gfortran.dg/pr91496.f90: New testcase.
From-SVN: r274966
-rw-r--r-- | gcc/fortran/ChangeLog | 18 | ||||
-rw-r--r-- | gcc/fortran/array.c | 3 | ||||
-rw-r--r-- | gcc/fortran/decl.c | 55 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 6 | ||||
-rw-r--r-- | gcc/fortran/gfortran.texi | 49 | ||||
-rw-r--r-- | gcc/fortran/match.h | 5 | ||||
-rw-r--r-- | gcc/fortran/parse.c | 34 | ||||
-rw-r--r-- | gcc/fortran/trans-stmt.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/pr91496.f90 | 38 |
10 files changed, 238 insertions, 2 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 3d8e49a..4ef8106 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,21 @@ +2019-08-27 Harald Anlauf <anlauf@gmx.de> + + PR fortran/91496 + * gfortran.h: Extend struct gfc_iterator for loop annotations. + * array.c (gfc_copy_iterator): Copy loop annotations by IVDEP, + VECTOR, and NOVECTOR pragmas. + * decl.c (gfc_match_gcc_ivdep, gfc_match_gcc_vector) + (gfc_match_gcc_novector): New matcher functions handling IVDEP, + VECTOR, and NOVECTOR pragmas. + * match.h: Declare prototypes of matcher functions handling IVDEP, + VECTOR, and NOVECTOR pragmas. + * parse.c (decode_gcc_attribute, parse_do_block) + (parse_executable): Decode IVDEP, VECTOR, and NOVECTOR pragmas; + emit warning for unrecognized pragmas instead of error. + * trans-stmt.c (gfc_trans_simple_do, gfc_trans_do): Add code to + emit annotations for IVDEP, VECTOR, and NOVECTOR pragmas. + * gfortran.texi: Document IVDEP, VECTOR, and NOVECTOR pragmas. + 2019-08-27 Mark Eggleston <mark.eggleston@codethink.com> * invoke.texi: Ensure that the option lists fit within the diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c index 396dd97..b958e89 100644 --- a/gcc/fortran/array.c +++ b/gcc/fortran/array.c @@ -2185,6 +2185,9 @@ gfc_copy_iterator (gfc_iterator *src) 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; return dest; } diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c index 5f12fe1..d5c8c33 100644 --- a/gcc/fortran/decl.c +++ b/gcc/fortran/decl.c @@ -99,6 +99,11 @@ bool gfc_matching_function; /* Set upon parsing a !GCC$ unroll n directive for use in the next loop. */ int directive_unroll = -1; +/* Set upon parsing supported !GCC$ pragmas for use in the next loop. */ +bool directive_ivdep = false; +bool directive_vector = false; +bool directive_novector = false; + /* Map of middle-end built-ins that should be vectorized. */ hash_map<nofree_string_hash, int> *gfc_vectorized_builtins; @@ -11528,3 +11533,53 @@ gfc_match_gcc_builtin (void) return MATCH_YES; } + +/* Match an !GCC$ IVDEP statement. + When we come here, we have already matched the !GCC$ IVDEP string. */ + +match +gfc_match_gcc_ivdep (void) +{ + if (gfc_match_eos () == MATCH_YES) + { + directive_ivdep = true; + return MATCH_YES; + } + + gfc_error ("Syntax error in !GCC$ IVDEP directive at %C"); + return MATCH_ERROR; +} + +/* Match an !GCC$ VECTOR statement. + When we come here, we have already matched the !GCC$ VECTOR string. */ + +match +gfc_match_gcc_vector (void) +{ + if (gfc_match_eos () == MATCH_YES) + { + directive_vector = true; + directive_novector = false; + return MATCH_YES; + } + + gfc_error ("Syntax error in !GCC$ VECTOR directive at %C"); + return MATCH_ERROR; +} + +/* Match an !GCC$ NOVECTOR statement. + When we come here, we have already matched the !GCC$ NOVECTOR string. */ + +match +gfc_match_gcc_novector (void) +{ + if (gfc_match_eos () == MATCH_YES) + { + directive_novector = true; + directive_vector = false; + return MATCH_YES; + } + + gfc_error ("Syntax error in !GCC$ NOVECTOR directive at %C"); + return MATCH_ERROR; +} diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 7f54897..d2f40df 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2418,6 +2418,9 @@ typedef struct { gfc_expr *var, *start, *end, *step; unsigned short unroll; + bool ivdep; + bool vector; + bool novector; } gfc_iterator; @@ -2794,6 +2797,9 @@ gfc_finalizer; bool gfc_in_match_data (void); match gfc_match_char_spec (gfc_typespec *); extern int directive_unroll; +extern bool directive_ivdep; +extern bool directive_vector; +extern bool directive_novector; /* SIMD clause enum. */ enum gfc_simd_clause diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi index 4515b9d..22d42f4 100644 --- a/gcc/fortran/gfortran.texi +++ b/gcc/fortran/gfortran.texi @@ -3559,6 +3559,9 @@ as this requires the new array descriptor. * ATTRIBUTES directive:: * UNROLL directive:: * BUILTIN directive:: +* IVDEP directive:: +* VECTOR directive:: +* NOVECTOR directive:: @end menu @node ATTRIBUTES directive @@ -3670,6 +3673,52 @@ for the built-in that should be vectorized. Example usage: The purpose of the directive is to provide an API among the GCC compiler and the GNU C Library which would define vector implementations of math routines. + +@node IVDEP directive +@subsection IVDEP directive + +The syntax of the directive is + +@code{!GCC$ ivdep} + +This directive tells the compiler to ignore vector dependencies in the +following loop. It must be placed immediately before a @code{DO} loop +and applies only to the loop that follows. + +Sometimes the compiler may not have sufficient information to decide +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. + +This directive is intended for annotation of existing code. For new +code it is recommended to consider OpenMP SIMD directives as potential +alternative. + + +@node VECTOR directive +@subsection VECTOR directive + +The syntax of the directive is + +@code{!GCC$ vector} + +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. + + +@node NOVECTOR directive +@subsection NOVECTOR directive + +The syntax of the directive is + +@code{!GCC$ novector} + +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. + + @node Non-Fortran Main Program @section Non-Fortran Main Program diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h index ac47d99..29854ee 100644 --- a/gcc/fortran/match.h +++ b/gcc/fortran/match.h @@ -246,8 +246,11 @@ match gfc_match_contiguous (void); match gfc_match_dimension (void); match gfc_match_external (void); match gfc_match_gcc_attributes (void); -match gfc_match_gcc_unroll (void); match gfc_match_gcc_builtin (void); +match gfc_match_gcc_ivdep (void); +match gfc_match_gcc_novector (void); +match gfc_match_gcc_unroll (void); +match gfc_match_gcc_vector (void); match gfc_match_import (void); match gfc_match_intent (void); match gfc_match_intrinsic (void); diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c index 31466d2..8950b6a 100644 --- a/gcc/fortran/parse.c +++ b/gcc/fortran/parse.c @@ -1079,12 +1079,20 @@ decode_gcc_attribute (void) match ("attributes", gfc_match_gcc_attributes, ST_ATTR_DECL); match ("unroll", gfc_match_gcc_unroll, ST_NONE); match ("builtin", gfc_match_gcc_builtin, ST_NONE); + match ("ivdep", gfc_match_gcc_ivdep, ST_NONE); + match ("vector", gfc_match_gcc_vector, ST_NONE); + match ("novector", gfc_match_gcc_novector, ST_NONE); /* All else has failed, so give up. See if any of the matchers has stored an error message of some sort. */ if (!gfc_error_check ()) - gfc_error_now ("Unclassifiable GCC directive at %C"); + { + if (pedantic) + gfc_error_now ("Unclassifiable GCC directive at %C"); + else + gfc_warning_now (0, "Unclassifiable GCC directive at %C, ignored"); + } reject_statement (); @@ -4672,6 +4680,21 @@ parse_do_block (void) new_st.ext.iterator->unroll = directive_unroll; directive_unroll = -1; } + if (directive_ivdep) + { + new_st.ext.iterator->ivdep = directive_ivdep; + directive_ivdep = false; + } + if (directive_vector) + { + new_st.ext.iterator->vector = directive_vector; + directive_vector = false; + } + if (directive_novector) + { + new_st.ext.iterator->novector = directive_novector; + directive_novector = false; + } } else stree = NULL; @@ -5433,6 +5456,15 @@ parse_executable (gfc_statement st) if (directive_unroll != -1) gfc_error ("%<GCC unroll%> directive does not commence a loop at %C"); + if (directive_ivdep) + gfc_error ("%<GCC ivdep%> directive does not commence a loop at %C"); + + if (directive_vector) + gfc_error ("%<GCC vector%> directive does not commence a loop at %C"); + + if (directive_novector) + gfc_error ("%<GCC novector%> directive does not commence a loop at %C"); + st = next_statement (); } } diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c index 7c36563..3606880 100644 --- a/gcc/fortran/trans-stmt.c +++ b/gcc/fortran/trans-stmt.c @@ -2173,6 +2173,19 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar, build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, code->ext.iterator->unroll)); + if (code->ext.iterator->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) + 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) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, annot_expr_no_vector_kind), + integer_zero_node); + /* The loop exit. */ tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label); TREE_USED (exit_label) = 1; @@ -2503,6 +2516,20 @@ gfc_trans_do (gfc_code * code, tree exit_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)); + + if (code->ext.iterator->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) + 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) + cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, + build_int_cst (integer_type_node, annot_expr_no_vector_kind), + integer_zero_node); + tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label); tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, cond, tmp, build_empty_stmt (loc)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a8149f7..37133de 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-08-27 Harald Anlauf <anlauf@gmx.de> + + PR fortran/91496 + * gfortran.dg/pr91496.f90: New testcase. + 2019-08-27 Uroš Bizjak <ubizjak@gmail.com> * gcc.target/i386/sse4_1-round-roundeven-1.c (dg-options): diff --git a/gcc/testsuite/gfortran.dg/pr91496.f90 b/gcc/testsuite/gfortran.dg/pr91496.f90 new file mode 100644 index 0000000..cb31674 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/pr91496.f90 @@ -0,0 +1,38 @@ +! { dg-do compile } +! { dg-options "-fdump-tree-original" } +! +subroutine foo (a, b, c, n) + implicit none + real a(*), b(*), c(*) + integer :: i, n + external bar +!DIR$ unroll (4) +!GCC$ unroll 4 + do i = 1, n + a(i) = b(i) + c(i) + end do +!DIR$ ivdep +!GCC$ ivdep + do i = 1, n + a(i) = b(i) + c(i) + end do +!DIR$ vector +!GCC$ vector + do i = 1, n + a(i) = b(i) + c(i) + end do +!DIR$ novector +!GCC$ novector + do i = 1, n + a(i) = b(i) + c(i) + end do +!GCC$ ivdep +!GCC$ vector + do i = 1, n + a(i) = b(i) + c(i) + end do +!DIR$ noinline +!GCC$ noinline ! { dg-warning "Unclassifiable GCC directive" } + call bar (a) +end subroutine foo +! { dg-final { scan-tree-dump-times "ANNOTATE_EXPR" 6 "original" } } |