aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHarald Anlauf <anlauf@gmx.de>2019-08-27 19:16:33 +0000
committerHarald Anlauf <anlauf@gcc.gnu.org>2019-08-27 19:16:33 +0000
commit2bd86b95f76315f102c52a81453ef375c97e8f1b (patch)
treeb7b05454a14ad73627667f20119d26edd65542b7
parent340d34bf76dd9455ab07ea849168bf2503d5edef (diff)
downloadgcc-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/ChangeLog18
-rw-r--r--gcc/fortran/array.c3
-rw-r--r--gcc/fortran/decl.c55
-rw-r--r--gcc/fortran/gfortran.h6
-rw-r--r--gcc/fortran/gfortran.texi49
-rw-r--r--gcc/fortran/match.h5
-rw-r--r--gcc/fortran/parse.c34
-rw-r--r--gcc/fortran/trans-stmt.c27
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/pr91496.f9038
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" } }