aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2018-11-27 14:06:48 +0100
committerMartin Liska <marxin@gcc.gnu.org>2018-11-27 13:06:48 +0000
commitfacf0354cfdaa555f376311b9d3c8fec79747f09 (patch)
tree3ef0c2c2a134b5685f82b8144402a410645d79a7 /gcc/fortran
parent2ff5ffb623e17b6bb81532394cb1f42fe7b354c8 (diff)
downloadgcc-facf0354cfdaa555f376311b9d3c8fec79747f09.zip
gcc-facf0354cfdaa555f376311b9d3c8fec79747f09.tar.gz
gcc-facf0354cfdaa555f376311b9d3c8fec79747f09.tar.bz2
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
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog16
-rw-r--r--gcc/fortran/decl.c41
-rw-r--r--gcc/fortran/gfortran.h22
-rw-r--r--gcc/fortran/lang-specs.h10
-rw-r--r--gcc/fortran/lang.opt4
-rw-r--r--gcc/fortran/match.h1
-rw-r--r--gcc/fortran/parse.c3
-rw-r--r--gcc/fortran/scanner.c4
-rw-r--r--gcc/fortran/trans-intrinsic.c70
9 files changed, 169 insertions, 2 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 7c15def..06e7400 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,19 @@
+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>
PR fortran/88143
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 2b77d95..ac86798 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -98,6 +98,9 @@ bool gfc_matching_function;
/* Set upon parsing a !GCC$ unroll n directive for use in the next loop. */
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
parameterized, temporarily store the expression here. */
static gfc_expr *saved_kind_expr = NULL;
@@ -11243,3 +11246,41 @@ gfc_match_gcc_unroll (void)
gfc_error ("Syntax error in !GCC$ UNROLL directive at %C");
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;
+}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 530e007..4dd6298 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2764,6 +2764,27 @@ bool gfc_in_match_data (void);
match gfc_match_char_spec (gfc_typespec *);
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 */
bool gfc_insert_kind_parameter_exprs (gfc_expr *);
bool gfc_insert_parameter_exprs (gfc_expr *, gfc_actual_arglist *);
@@ -3502,5 +3523,6 @@ bool gfc_is_reallocatable_lhs (gfc_expr *);
/* trans-decl.c */
void finish_oacc_declare (gfc_namespace *, gfc_symbol *, bool);
+void gfc_adjust_builtins (void);
#endif /* GCC_GFORTRAN_H */
diff --git a/gcc/fortran/lang-specs.h b/gcc/fortran/lang-specs.h
index c3ab970..61a9118 100644
--- a/gcc/fortran/lang-specs.h
+++ b/gcc/fortran/lang-specs.h
@@ -32,9 +32,15 @@
#define F951_CPP_OPTIONS "%{!nocpp: -cpp=%g.f90 %{E} %(cpp_unique_options) \
%{E|M|MM:%(cpp_debug_options) " CPP_ONLY_OPTIONS \
" -fsyntax-only};: " CPP_FORWARD_OPTIONS "}"
+
+#ifndef TARGET_F951_OPTIONS
+#define TARGET_F951_OPTIONS
+#endif
+
#define F951_OPTIONS "%(cc1_options) %{J*} \
- %{!nostdinc:-fintrinsic-modules-path finclude%s}\
- %{!fsyntax-only:%(invoke_as)}"
+ %{!nostdinc:-fintrinsic-modules-path finclude%s}" \
+ TARGET_F951_OPTIONS \
+ "%{!fsyntax-only:%(invoke_as)}"
#define F951_SOURCE_FORM "%{!ffree-form:-ffixed-form}"
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index ae4957e..dc9a94c 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -670,6 +670,10 @@ fprotect-parens
Fortran Var(flag_protect_parens) Init(-1)
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
Fortran Var(flag_range_check) Init(1)
Enable range checking during compilation.
diff --git a/gcc/fortran/match.h b/gcc/fortran/match.h
index 418542b..f25ed86 100644
--- a/gcc/fortran/match.h
+++ b/gcc/fortran/match.h
@@ -247,6 +247,7 @@ 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_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 13cc6f5..56d0d05 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -1072,6 +1072,7 @@ 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);
/* All else has failed, so give up. See if any of the matchers has
stored an error message of some sort. */
@@ -5663,6 +5664,8 @@ parse_progunit (gfc_statement st)
gfc_state_data *p;
int n;
+ gfc_adjust_builtins ();
+
if (gfc_new_block
&& gfc_new_block->abr_modproc_decl
&& gfc_new_block->attr.function)
diff --git a/gcc/fortran/scanner.c b/gcc/fortran/scanner.c
index 2ef32b2..a79689a 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -2677,6 +2677,10 @@ gfc_new_file (void)
{
bool result;
+ if (flag_pre_include != NULL
+ && !load_file (flag_pre_include, NULL, false))
+ exit (FATAL_EXIT_CODE);
+
if (gfc_cpp_enabled ())
{
result = gfc_cpp_preprocess (gfc_source_file);
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 4ae2b32..40a7491 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -597,7 +597,77 @@ define_quad_builtin (const char *name, tree type, bool is_const)
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
are created as required. Builtin functions are added here. */