Commit facf0354 by Martin Liska Committed by Martin Liska

Support simd function declarations via a pre-include.

2018-11-27  Martin Liska  <mliska@suse.cz>

	* config/gnu-user.h (TARGET_F951_OPTIONS): New.
	* gcc.c (find_fortran_preinclude_file): New function
	to handle Fortran pre-include.
2018-11-27  Martin Liska  <mliska@suse.cz>

	* decl.c (gfc_match_gcc_builtin): New function.
	* gfortran.h (struct vect_builtin_tuple): New.
	(gfc_adjust_builtins): Likewise.
	* lang-specs.h (TARGET_F951_OPTIONS): New.
	(F951_OPTIONS): Use it.
	* lang.opt: Add new option -fpre-include.
	* match.h (gfc_match_gcc_builtin): Declare new function.
	* parse.c (decode_gcc_attribute): Handle builtin.
	(parse_progunit): Call gfc_adjust_builtins.
	* scanner.c (gfc_new_file): Load pre-included header file
	when provided.
	* trans-intrinsic.c (add_simd_flag_for_built_in): New.
	(gfc_adjust_builtins): Likewise.
2018-11-27  Martin Liska  <mliska@suse.cz>

	* gfortran.dg/simd-builtins-1.f90: New test.
	* gfortran.dg/simd-builtins-1.h: New test.
	* gfortran.dg/simd-builtins-2.f90: New test.
	* gfortran.dg/simd-builtins-3.f90: New test.
	* gfortran.dg/simd-builtins-3.h: New test.
	* gfortran.dg/simd-builtins-4.f: New test.
	* gfortran.dg/simd-builtins-4.h: New test.
	* gfortran.dg/simd-builtins-5.f: New test.
	* gfortran.dg/simd-builtins-6.f90: New test.

From-SVN: r266509
parent 2ff5ffb6
2018-11-27 Martin Liska <mliska@suse.cz> 2018-11-27 Martin Liska <mliska@suse.cz>
* config/gnu-user.h (TARGET_F951_OPTIONS): New.
* gcc.c (find_fortran_preinclude_file): New function
to handle Fortran pre-include.
2018-11-27 Martin Liska <mliska@suse.cz>
* asan.c (asan_emit_stack_protection): Use new enum values * asan.c (asan_emit_stack_protection): Use new enum values
instead of int constants. instead of int constants.
* builtins.c (expand_builtin_memory_copy_args): Replace int * builtins.c (expand_builtin_memory_copy_args): Replace int
...@@ -148,3 +148,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see ...@@ -148,3 +148,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
LD_STATIC_OPTION " --whole-archive -llsan --no-whole-archive " \ LD_STATIC_OPTION " --whole-archive -llsan --no-whole-archive " \
LD_DYNAMIC_OPTION "}}%{!static-liblsan:-llsan}" LD_DYNAMIC_OPTION "}}%{!static-liblsan:-llsan}"
#endif #endif
#undef TARGET_F951_OPTIONS
#define TARGET_F951_OPTIONS "%{!nostdinc:\
%:fortran-preinclude-file(-fpre-include= math-vector-fortran.h)}"
2018-11-27 Martin Liska <mliska@suse.cz>
* decl.c (gfc_match_gcc_builtin): New function.
* gfortran.h (struct vect_builtin_tuple): New.
(gfc_adjust_builtins): Likewise.
* lang-specs.h (TARGET_F951_OPTIONS): New.
(F951_OPTIONS): Use it.
* lang.opt: Add new option -fpre-include.
* match.h (gfc_match_gcc_builtin): Declare new function.
* parse.c (decode_gcc_attribute): Handle builtin.
(parse_progunit): Call gfc_adjust_builtins.
* scanner.c (gfc_new_file): Load pre-included header file
when provided.
* trans-intrinsic.c (add_simd_flag_for_built_in): New.
(gfc_adjust_builtins): Likewise.
2018-11-24 Paul Thomas <pault@gcc.gnu.org> 2018-11-24 Paul Thomas <pault@gcc.gnu.org>
PR fortran/88143 PR fortran/88143
......
...@@ -98,6 +98,9 @@ bool gfc_matching_function; ...@@ -98,6 +98,9 @@ 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;
/* Map of middle-end built-ins that should be vectorized. */
hash_map<nofree_string_hash, int> *gfc_vectorized_builtins;
/* If a kind expression of a component of a parameterized derived type is /* If a kind expression of a component of a parameterized derived type is
parameterized, temporarily store the expression here. */ parameterized, temporarily store the expression here. */
static gfc_expr *saved_kind_expr = NULL; static gfc_expr *saved_kind_expr = NULL;
...@@ -11243,3 +11246,41 @@ gfc_match_gcc_unroll (void) ...@@ -11243,3 +11246,41 @@ gfc_match_gcc_unroll (void)
gfc_error ("Syntax error in !GCC$ UNROLL directive at %C"); gfc_error ("Syntax error in !GCC$ UNROLL directive at %C");
return MATCH_ERROR; return MATCH_ERROR;
} }
/* Match a !GCC$ builtin (b) attributes simd flags form:
The parameter b is name of a middle-end built-in.
Flags are one of:
- (empty)
- inbranch
- notinbranch
When we come here, we have already matched the !GCC$ builtin string. */
match
gfc_match_gcc_builtin (void)
{
char builtin[GFC_MAX_SYMBOL_LEN + 1];
if (gfc_match (" ( %n ) attributes simd", builtin) != MATCH_YES)
return MATCH_ERROR;
gfc_simd_clause clause = SIMD_NONE;
if (gfc_match (" ( notinbranch ) ") == MATCH_YES)
clause = SIMD_NOTINBRANCH;
else if (gfc_match (" ( inbranch ) ") == MATCH_YES)
clause = SIMD_INBRANCH;
if (gfc_vectorized_builtins == NULL)
gfc_vectorized_builtins = new hash_map<nofree_string_hash, int> ();
char *r = XNEWVEC (char, strlen (builtin) + 32);
sprintf (r, "__builtin_%s", builtin);
bool existed;
int &value = gfc_vectorized_builtins->get_or_insert (r, &existed);
value |= clause;
if (existed)
free (r);
return MATCH_YES;
}
...@@ -2764,6 +2764,27 @@ bool gfc_in_match_data (void); ...@@ -2764,6 +2764,27 @@ 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;
/* SIMD clause enum. */
enum gfc_simd_clause
{
SIMD_NONE = (1 << 0),
SIMD_INBRANCH = (1 << 1),
SIMD_NOTINBRANCH = (1 << 2)
};
/* Tuple for parsing of vectorized built-ins. */
struct gfc_vect_builtin_tuple
{
gfc_vect_builtin_tuple (const char *n, gfc_simd_clause t)
: name (n), simd_type (t) {}
const char *name;
gfc_simd_clause simd_type;
};
/* Map of middle-end built-ins that should be vectorized. */
extern hash_map<nofree_string_hash, int> *gfc_vectorized_builtins;
/* Handling Parameterized Derived Types */ /* Handling Parameterized Derived Types */
bool gfc_insert_kind_parameter_exprs (gfc_expr *); bool gfc_insert_kind_parameter_exprs (gfc_expr *);
bool gfc_insert_parameter_exprs (gfc_expr *, gfc_actual_arglist *); bool gfc_insert_parameter_exprs (gfc_expr *, gfc_actual_arglist *);
...@@ -3502,5 +3523,6 @@ bool gfc_is_reallocatable_lhs (gfc_expr *); ...@@ -3502,5 +3523,6 @@ bool gfc_is_reallocatable_lhs (gfc_expr *);
/* trans-decl.c */ /* trans-decl.c */
void finish_oacc_declare (gfc_namespace *, gfc_symbol *, bool); void finish_oacc_declare (gfc_namespace *, gfc_symbol *, bool);
void gfc_adjust_builtins (void);
#endif /* GCC_GFORTRAN_H */ #endif /* GCC_GFORTRAN_H */
...@@ -32,9 +32,15 @@ ...@@ -32,9 +32,15 @@
#define F951_CPP_OPTIONS "%{!nocpp: -cpp=%g.f90 %{E} %(cpp_unique_options) \ #define F951_CPP_OPTIONS "%{!nocpp: -cpp=%g.f90 %{E} %(cpp_unique_options) \
%{E|M|MM:%(cpp_debug_options) " CPP_ONLY_OPTIONS \ %{E|M|MM:%(cpp_debug_options) " CPP_ONLY_OPTIONS \
" -fsyntax-only};: " CPP_FORWARD_OPTIONS "}" " -fsyntax-only};: " CPP_FORWARD_OPTIONS "}"
#ifndef TARGET_F951_OPTIONS
#define TARGET_F951_OPTIONS
#endif
#define F951_OPTIONS "%(cc1_options) %{J*} \ #define F951_OPTIONS "%(cc1_options) %{J*} \
%{!nostdinc:-fintrinsic-modules-path finclude%s}\ %{!nostdinc:-fintrinsic-modules-path finclude%s}" \
%{!fsyntax-only:%(invoke_as)}" TARGET_F951_OPTIONS \
"%{!fsyntax-only:%(invoke_as)}"
#define F951_SOURCE_FORM "%{!ffree-form:-ffixed-form}" #define F951_SOURCE_FORM "%{!ffree-form:-ffixed-form}"
......
...@@ -670,6 +670,10 @@ fprotect-parens ...@@ -670,6 +670,10 @@ fprotect-parens
Fortran Var(flag_protect_parens) Init(-1) Fortran Var(flag_protect_parens) Init(-1)
Protect parentheses in expressions. Protect parentheses in expressions.
fpre-include=
Fortran RejectNegative Joined Var(flag_pre_include) Undocumented
Path to header file that should be pre-included before each compilation unit.
frange-check frange-check
Fortran Var(flag_range_check) Init(1) Fortran Var(flag_range_check) Init(1)
Enable range checking during compilation. Enable range checking during compilation.
......
...@@ -247,6 +247,7 @@ match gfc_match_dimension (void); ...@@ -247,6 +247,7 @@ 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_unroll (void);
match gfc_match_gcc_builtin (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);
......
...@@ -1072,6 +1072,7 @@ decode_gcc_attribute (void) ...@@ -1072,6 +1072,7 @@ 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);
/* 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. */
...@@ -5663,6 +5664,8 @@ parse_progunit (gfc_statement st) ...@@ -5663,6 +5664,8 @@ parse_progunit (gfc_statement st)
gfc_state_data *p; gfc_state_data *p;
int n; int n;
gfc_adjust_builtins ();
if (gfc_new_block if (gfc_new_block
&& gfc_new_block->abr_modproc_decl && gfc_new_block->abr_modproc_decl
&& gfc_new_block->attr.function) && gfc_new_block->attr.function)
......
...@@ -2677,6 +2677,10 @@ gfc_new_file (void) ...@@ -2677,6 +2677,10 @@ gfc_new_file (void)
{ {
bool result; bool result;
if (flag_pre_include != NULL
&& !load_file (flag_pre_include, NULL, false))
exit (FATAL_EXIT_CODE);
if (gfc_cpp_enabled ()) if (gfc_cpp_enabled ())
{ {
result = gfc_cpp_preprocess (gfc_source_file); result = gfc_cpp_preprocess (gfc_source_file);
......
...@@ -597,7 +597,77 @@ define_quad_builtin (const char *name, tree type, bool is_const) ...@@ -597,7 +597,77 @@ define_quad_builtin (const char *name, tree type, bool is_const)
return fndecl; return fndecl;
} }
/* Add SIMD attribute for FNDECL built-in if the built-in
name is in VECTORIZED_BUILTINS. */
static void
add_simd_flag_for_built_in (tree fndecl)
{
if (gfc_vectorized_builtins == NULL
|| fndecl == NULL_TREE)
return;
const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
int *clauses = gfc_vectorized_builtins->get (name);
if (clauses)
{
for (unsigned i = 0; i < 3; i++)
if (*clauses & (1 << i))
{
gfc_simd_clause simd_type = (gfc_simd_clause)*clauses;
tree omp_clause = NULL_TREE;
if (simd_type == SIMD_NONE)
; /* No SIMD clause. */
else
{
omp_clause_code code
= (simd_type == SIMD_INBRANCH
? OMP_CLAUSE_INBRANCH : OMP_CLAUSE_NOTINBRANCH);
omp_clause = build_omp_clause (UNKNOWN_LOCATION, code);
omp_clause = build_tree_list (NULL_TREE, omp_clause);
}
DECL_ATTRIBUTES (fndecl)
= tree_cons (get_identifier ("omp declare simd"), omp_clause,
DECL_ATTRIBUTES (fndecl));
}
}
}
/* Set SIMD attribute to all built-in functions that are mentioned
in gfc_vectorized_builtins vector. */
void
gfc_adjust_builtins (void)
{
gfc_intrinsic_map_t *m;
for (m = gfc_intrinsic_map;
m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
{
add_simd_flag_for_built_in (m->real4_decl);
add_simd_flag_for_built_in (m->complex4_decl);
add_simd_flag_for_built_in (m->real8_decl);
add_simd_flag_for_built_in (m->complex8_decl);
add_simd_flag_for_built_in (m->real10_decl);
add_simd_flag_for_built_in (m->complex10_decl);
add_simd_flag_for_built_in (m->real16_decl);
add_simd_flag_for_built_in (m->complex16_decl);
add_simd_flag_for_built_in (m->real16_decl);
add_simd_flag_for_built_in (m->complex16_decl);
}
/* Release all strings. */
if (gfc_vectorized_builtins != NULL)
{
for (hash_map<nofree_string_hash, int>::iterator it
= gfc_vectorized_builtins->begin ();
it != gfc_vectorized_builtins->end (); ++it)
free (CONST_CAST (char *, (*it).first));
delete gfc_vectorized_builtins;
gfc_vectorized_builtins = NULL;
}
}
/* Initialize function decls for library functions. The external functions /* Initialize function decls for library functions. The external functions
are created as required. Builtin functions are added here. */ are created as required. Builtin functions are added here. */
......
...@@ -408,6 +408,7 @@ static const char *pass_through_libs_spec_func (int, const char **); ...@@ -408,6 +408,7 @@ static const char *pass_through_libs_spec_func (int, const char **);
static const char *replace_extension_spec_func (int, const char **); static const char *replace_extension_spec_func (int, const char **);
static const char *greater_than_spec_func (int, const char **); static const char *greater_than_spec_func (int, const char **);
static const char *debug_level_greater_than_spec_func (int, const char **); static const char *debug_level_greater_than_spec_func (int, const char **);
static const char *find_fortran_preinclude_file (int, const char **);
static char *convert_white_space (char *); static char *convert_white_space (char *);
/* The Specs Language /* The Specs Language
...@@ -1647,6 +1648,7 @@ static const struct spec_function static_spec_functions[] = ...@@ -1647,6 +1648,7 @@ static const struct spec_function static_spec_functions[] =
{ "replace-extension", replace_extension_spec_func }, { "replace-extension", replace_extension_spec_func },
{ "gt", greater_than_spec_func }, { "gt", greater_than_spec_func },
{ "debug-level-gt", debug_level_greater_than_spec_func }, { "debug-level-gt", debug_level_greater_than_spec_func },
{ "fortran-preinclude-file", find_fortran_preinclude_file},
#ifdef EXTRA_SPEC_FUNCTIONS #ifdef EXTRA_SPEC_FUNCTIONS
EXTRA_SPEC_FUNCTIONS EXTRA_SPEC_FUNCTIONS
#endif #endif
...@@ -9894,6 +9896,23 @@ debug_level_greater_than_spec_func (int argc, const char **argv) ...@@ -9894,6 +9896,23 @@ debug_level_greater_than_spec_func (int argc, const char **argv)
return NULL; return NULL;
} }
/* The function takes 2 arguments: OPTION name and file name.
When the FILE is found by find_file, return OPTION=path_to_file. */
static const char *
find_fortran_preinclude_file (int argc, const char **argv)
{
if (argc != 2)
return NULL;
const char *path = find_a_file (&include_prefixes, argv[1], R_OK, true);
if (path != NULL)
return concat (argv[0], path, NULL);
return NULL;
}
/* Insert backslash before spaces in ORIG (usually a file path), to /* Insert backslash before spaces in ORIG (usually a file path), to
avoid being broken by spec parser. avoid being broken by spec parser.
......
2018-11-27 Martin Liska <mliska@suse.cz>
* gfortran.dg/simd-builtins-1.f90: New test.
* gfortran.dg/simd-builtins-1.h: New test.
* gfortran.dg/simd-builtins-2.f90: New test.
* gfortran.dg/simd-builtins-3.f90: New test.
* gfortran.dg/simd-builtins-3.h: New test.
* gfortran.dg/simd-builtins-4.f: New test.
* gfortran.dg/simd-builtins-4.h: New test.
* gfortran.dg/simd-builtins-5.f: New test.
* gfortran.dg/simd-builtins-6.f90: New test.
2018-11-27 Jozef Lawrynowicz <jozef.l@mittosystems.com> 2018-11-27 Jozef Lawrynowicz <jozef.l@mittosystems.com>
* lib/target-supports.exp * lib/target-supports.exp
......
! { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } }
! { dg-additional-options "-msse2 -nostdinc -Ofast -fpre-include=simd-builtins-1.h -fdump-tree-optimized" }
program test_overloaded_intrinsic
real(4) :: x4(3200), y4(3200)
real(8) :: x8(3200), y8(3200)
! this should be using simd clone
y4 = sin(x4)
print *, y4
! this should not be using simd clone
y4 = sin(x8)
print *, y8
end
! { dg-final { scan-tree-dump "sinf.simdclone" "optimized" } } */
! { dg-final { scan-tree-dump "__builtin_sin" "optimized" } } */
! { dg-final { scan-assembler "call.*_ZGVbN4v_sinf" } }
!GCC$ builtin (sin) attributes simd (inbranch)
!GCC$ builtin (sinf) attributes simd (notinbranch)
!GCC$ builtin (cosf) attributes simd
!GCC$ builtin (cosf) attributes simd (notinbranch)
! { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } }
! { dg-additional-options "-msse2 -nostdinc -Ofast -fdump-tree-optimized" }
program test_overloaded_intrinsic
real(4) :: x4(3200), y4(3200)
real(8) :: x8(3200), y8(3200)
! this should be using simd clone
y4 = sin(x4)
print *, y4
! this should not be using simd clone
y4 = sin(x8)
print *, y8
end
! { dg-final { scan-tree-dump "__builtin_sinf" "optimized" } } */
! { dg-final { scan-tree-dump "__builtin_sin" "optimized" } } */
! { dg-final { scan-tree-dump-not "simdclone" "optimized" } } */
! { dg-final { scan-assembler-not "call.*_ZGVbN4v_sinf" } }
! { dg-additional-options "-nostdinc -fpre-include=simd-builtins-3.h" }
!GCC$ builtin (sin) attributes simd (inbranch)
!GCC$ builtin ( sin) attributes simd (inbranch)
!GCC$ builtin (sin ) attributes simd (inbranch)
!GCC$ builtin (sin) attributes simd ( inbranch)
!GCC$ builtin (sin) attributes simd (inbranch )
!GCC$ builtin(sin ) attributes simd ( inbranch )
!GCC$ builtin ( sin ) attributes simd ( inbranch )
!GCC$ builtin ( sin ) attributes simd
! { dg-additional-options "-nostdinc -fpre-include=simd-builtins-4.h" }
!GCC$ builtin (sin) attributes simd (inbranch)
!GCC$ builtin ( sin) attributes simd (inbranch)
!GCC$ builtin (sin ) attributes simd (inbranch)
!GCC$ builtin (sin) attributes simd ( inbranch)
!GCC$ builtin (sin) attributes simd (inbranch )
!GCC$ builtin(sin ) attributes simd ( inbranch )
!GCC$ builtin ( sin ) attributes simd ( inbranch )
!GCC$ builtin ( sin ) attributes simd
! { dg-do compile }
!GCC$ buil tin (s in) attributes simd (inbranch)
!GCC$ builtin (sinf) at tributes simd (notinbranch)
!GCC$ builtin (cosf) att r i bu tes s imd
!GCC$ buil ti n ( cosf) attrib utes simd (noti nbranch)
PROGRAM Z
END
! { dg-do compile { target { i?86-*-linux* x86_64-*-linux* } } }
! { dg-additional-options "-msse2 -nostdinc -Ofast -fdump-tree-optimized" }
!GCC$ builtin (sin) attributes simd (inbranch)
!GCC$ builtin (sinf) attributes simd (notinbranch)
!GCC$ builtin (cosf) attributes simd
!GCC$ builtin (cosf) attributes simd (notinbranch)
program test_overloaded_intrinsic
real(4) :: x4(3200), y4(3200)
real(8) :: x8(3200), y8(3200)
! this should be using simd clone
y4 = sin(x4)
print *, y4
! this should not be using simd clone
y4 = sin(x8)
print *, y8
end
! { dg-final { scan-tree-dump "sinf.simdclone" "optimized" } } */
! { dg-final { scan-tree-dump "__builtin_sin" "optimized" } } */
! { dg-final { scan-assembler "call.*_ZGVbN4v_sinf" } }
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