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
This commit is contained in:
Harald Anlauf 2019-08-27 19:16:33 +00:00 committed by Harald Anlauf
parent 340d34bf76
commit 2bd86b95f7
10 changed files with 238 additions and 2 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 ();
}
}

View File

@ -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));

View File

@ -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):

View File

@ -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" } }