Dear all, the attached patch adds Fortran support for the following pragmas (loop annotations): IVDEP (ignore vector dependencies), VECTOR, and NOVECTOR. Furthermore, it downgrades unsupported directives from error to warning (by default, it stays an error with -pedantic), thus fixing the PR.
It has no effect on existing code (thus regtested cleanly on x86_64-pc-linux-gnu), but gives users an option for fine-grained control of optimization. The above pragmas are supported by other compilers (with different sentinels, e.g. !DIR$ for Intel, Cray, sometimes with slightly different keywords). OK for trunk, and backport to 9? Thanks, Harald 2019-08-26 Harald Anlauf <anl...@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-26 Harald Anlauf <anl...@gmx.de> PR fortran/91496 * gfortran.dg/pr91496.f90: New testcase.
Index: gcc/fortran/array.c =================================================================== --- gcc/fortran/array.c (revision 274933) +++ gcc/fortran/array.c (working copy) @@ -2185,6 +2185,9 @@ 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; } Index: gcc/fortran/decl.c =================================================================== --- gcc/fortran/decl.c (revision 274933) +++ gcc/fortran/decl.c (working copy) @@ -99,6 +99,11 @@ /* 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,57 @@ 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) +{ + int value; + + 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) +{ + int value; + + if (gfc_match_eos () == MATCH_YES) + { + directive_vector = true; + 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) +{ + int value; + + if (gfc_match_eos () == MATCH_YES) + { + directive_novector = true; + return MATCH_YES; + } + + gfc_error ("Syntax error in !GCC$ NOVECTOR directive at %C"); + return MATCH_ERROR; +} Index: gcc/fortran/gfortran.h =================================================================== --- gcc/fortran/gfortran.h (revision 274933) +++ gcc/fortran/gfortran.h (working copy) @@ -2418,6 +2418,9 @@ { gfc_expr *var, *start, *end, *step; unsigned short unroll; + bool ivdep; + bool vector; + bool novector; } gfc_iterator; @@ -2794,6 +2797,9 @@ 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 Index: gcc/fortran/gfortran.texi =================================================================== --- gcc/fortran/gfortran.texi (revision 274933) +++ gcc/fortran/gfortran.texi (working copy) @@ -3559,6 +3559,9 @@ * ATTRIBUTES directive:: * UNROLL directive:: * BUILTIN directive:: +* IVDEP directive:: +* VECTOR directive:: +* NOVECTOR directive:: @end menu @node ATTRIBUTES directive @@ -3670,6 +3673,52 @@ 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 Index: gcc/fortran/match.h =================================================================== --- gcc/fortran/match.h (revision 274933) +++ gcc/fortran/match.h (working copy) @@ -246,8 +246,11 @@ match gfc_match_dimension (void); match gfc_match_external (void); match gfc_match_gcc_attributes (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_builtin (void); +match gfc_match_gcc_vector (void); match gfc_match_import (void); match gfc_match_intent (void); match gfc_match_intrinsic (void); Index: gcc/fortran/parse.c =================================================================== --- gcc/fortran/parse.c (revision 274933) +++ gcc/fortran/parse.c (working copy) @@ -1079,12 +1079,20 @@ 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 @@ 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 @@ 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 (); } } Index: gcc/fortran/trans-stmt.c =================================================================== --- gcc/fortran/trans-stmt.c (revision 274933) +++ gcc/fortran/trans-stmt.c (working copy) @@ -2173,6 +2173,19 @@ 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 @@ = 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));
Index: gcc/testsuite/gfortran.dg/pr91496.f90 =================================================================== --- gcc/testsuite/gfortran.dg/pr91496.f90 (nonexistent) +++ gcc/testsuite/gfortran.dg/pr91496.f90 (working copy) @@ -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" } }