Commit 2bd86b95 by Harald Anlauf Committed by Harald Anlauf

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
parent 340d34bf
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> 2019-08-27 Mark Eggleston <mark.eggleston@codethink.com>
* invoke.texi: Ensure that the option lists fit within the * invoke.texi: Ensure that the option lists fit within the
......
...@@ -2185,6 +2185,9 @@ gfc_copy_iterator (gfc_iterator *src) ...@@ -2185,6 +2185,9 @@ gfc_copy_iterator (gfc_iterator *src)
dest->end = gfc_copy_expr (src->end); dest->end = gfc_copy_expr (src->end);
dest->step = gfc_copy_expr (src->step); dest->step = gfc_copy_expr (src->step);
dest->unroll = src->unroll; dest->unroll = src->unroll;
dest->ivdep = src->ivdep;
dest->vector = src->vector;
dest->novector = src->novector;
return dest; return dest;
} }
......
...@@ -99,6 +99,11 @@ bool gfc_matching_function; ...@@ -99,6 +99,11 @@ bool gfc_matching_function;
/* Set upon parsing a !GCC$ unroll n directive for use in the next loop. */ /* Set upon parsing a !GCC$ unroll n directive for use in the next loop. */
int directive_unroll = -1; 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. */ /* Map of middle-end built-ins that should be vectorized. */
hash_map<nofree_string_hash, int> *gfc_vectorized_builtins; hash_map<nofree_string_hash, int> *gfc_vectorized_builtins;
...@@ -11528,3 +11533,53 @@ gfc_match_gcc_builtin (void) ...@@ -11528,3 +11533,53 @@ gfc_match_gcc_builtin (void)
return MATCH_YES; 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;
}
...@@ -2418,6 +2418,9 @@ typedef struct ...@@ -2418,6 +2418,9 @@ typedef struct
{ {
gfc_expr *var, *start, *end, *step; gfc_expr *var, *start, *end, *step;
unsigned short unroll; unsigned short unroll;
bool ivdep;
bool vector;
bool novector;
} }
gfc_iterator; gfc_iterator;
...@@ -2794,6 +2797,9 @@ gfc_finalizer; ...@@ -2794,6 +2797,9 @@ gfc_finalizer;
bool gfc_in_match_data (void); bool gfc_in_match_data (void);
match gfc_match_char_spec (gfc_typespec *); match gfc_match_char_spec (gfc_typespec *);
extern int directive_unroll; extern int directive_unroll;
extern bool directive_ivdep;
extern bool directive_vector;
extern bool directive_novector;
/* SIMD clause enum. */ /* SIMD clause enum. */
enum gfc_simd_clause enum gfc_simd_clause
......
...@@ -3559,6 +3559,9 @@ as this requires the new array descriptor. ...@@ -3559,6 +3559,9 @@ as this requires the new array descriptor.
* ATTRIBUTES directive:: * ATTRIBUTES directive::
* UNROLL directive:: * UNROLL directive::
* BUILTIN directive:: * BUILTIN directive::
* IVDEP directive::
* VECTOR directive::
* NOVECTOR directive::
@end menu @end menu
@node ATTRIBUTES directive @node ATTRIBUTES directive
...@@ -3670,6 +3673,52 @@ for the built-in that should be vectorized. Example usage: ...@@ -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 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. 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 @node Non-Fortran Main Program
@section Non-Fortran Main Program @section Non-Fortran Main Program
......
...@@ -246,8 +246,11 @@ match gfc_match_contiguous (void); ...@@ -246,8 +246,11 @@ match gfc_match_contiguous (void);
match gfc_match_dimension (void); match gfc_match_dimension (void);
match gfc_match_external (void); match gfc_match_external (void);
match gfc_match_gcc_attributes (void); match gfc_match_gcc_attributes (void);
match gfc_match_gcc_unroll (void);
match gfc_match_gcc_builtin (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_import (void);
match gfc_match_intent (void); match gfc_match_intent (void);
match gfc_match_intrinsic (void); match gfc_match_intrinsic (void);
......
...@@ -1079,12 +1079,20 @@ decode_gcc_attribute (void) ...@@ -1079,12 +1079,20 @@ decode_gcc_attribute (void)
match ("attributes", gfc_match_gcc_attributes, ST_ATTR_DECL); match ("attributes", gfc_match_gcc_attributes, ST_ATTR_DECL);
match ("unroll", gfc_match_gcc_unroll, ST_NONE); match ("unroll", gfc_match_gcc_unroll, ST_NONE);
match ("builtin", gfc_match_gcc_builtin, 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 /* All else has failed, so give up. See if any of the matchers has
stored an error message of some sort. */ stored an error message of some sort. */
if (!gfc_error_check ()) 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 (); reject_statement ();
...@@ -4672,6 +4680,21 @@ parse_do_block (void) ...@@ -4672,6 +4680,21 @@ parse_do_block (void)
new_st.ext.iterator->unroll = directive_unroll; new_st.ext.iterator->unroll = directive_unroll;
directive_unroll = -1; 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 else
stree = NULL; stree = NULL;
...@@ -5433,6 +5456,15 @@ parse_executable (gfc_statement st) ...@@ -5433,6 +5456,15 @@ parse_executable (gfc_statement st)
if (directive_unroll != -1) if (directive_unroll != -1)
gfc_error ("%<GCC unroll%> directive does not commence a loop at %C"); 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 (); st = next_statement ();
} }
} }
......
...@@ -2173,6 +2173,19 @@ gfc_trans_simple_do (gfc_code * code, stmtblock_t *pblock, tree dovar, ...@@ -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, annot_expr_unroll_kind),
build_int_cst (integer_type_node, code->ext.iterator->unroll)); 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. */ /* The loop exit. */
tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label); tmp = fold_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
TREE_USED (exit_label) = 1; TREE_USED (exit_label) = 1;
...@@ -2503,6 +2516,20 @@ gfc_trans_do (gfc_code * code, tree exit_cond) ...@@ -2503,6 +2516,20 @@ gfc_trans_do (gfc_code * code, tree exit_cond)
= build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond,
build_int_cst (integer_type_node, annot_expr_unroll_kind), build_int_cst (integer_type_node, annot_expr_unroll_kind),
build_int_cst (integer_type_node, code->ext.iterator->unroll)); 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_build1_loc (loc, GOTO_EXPR, void_type_node, exit_label);
tmp = fold_build3_loc (loc, COND_EXPR, void_type_node, tmp = fold_build3_loc (loc, COND_EXPR, void_type_node,
cond, tmp, build_empty_stmt (loc)); cond, tmp, build_empty_stmt (loc));
......
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> 2019-08-27 Uroš Bizjak <ubizjak@gmail.com>
* gcc.target/i386/sse4_1-round-roundeven-1.c (dg-options): * gcc.target/i386/sse4_1-round-roundeven-1.c (dg-options):
......
! { 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" } }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment