Hi.

I'm CCing gcc-patches ML and Jakub, who significantly helped me yesterday. The
idea now is to have a driver search for the math header file. When it exists,
Fortran FE loads the file (via new -fpre-include option).

I can confirm that e.g. roms_r CPU2017 benchmark utilizes couple of simd clones:

$ grep simd *.optimized
analytical.fppized.f90.229t.optimized:  vect__77.555_90 = exp.simdclone.12 
(vect__76.554_94);
analytical.fppized.f90.229t.optimized:  vect__322.866_1061 = sin.simdclone.4 
(vect__321.865_1062);
bulk_flux.fppized.f90.229t.optimized:  vect__506.784_1887 = pow.simdclone.2 
(vect__1057.783_1889, { 
1.939999999999999946709294817992486059665679931640625e+0, 
1.939999999999999946709294817992486059665679931640625e+0 });
gasdev.fppized.f90.229t.optimized:  vect__66.139_93 = log.simdclone.0 
(vect__65.138_94);
lmd_swfrac.fppized.f90.229t.optimized:  vect__84.60_182 = exp.simdclone.0 
(vect__83.59_183);
lmd_swfrac.fppized.f90.229t.optimized:  vect__89.69_161 = exp.simdclone.0 
(vect__88.68_162);
marxin@marxinbox:~/Programming/cpu2017/benchspec/CPU/554.roms_r/build/build_peak_gcc7-m64.0000>
 grep simd *.optimized
analytical.fppized.f90.229t.optimized:  vect__77.555_90 = exp.simdclone.12 
(vect__76.554_94);
analytical.fppized.f90.229t.optimized:  vect__322.866_1061 = sin.simdclone.4 
(vect__321.865_1062);
bulk_flux.fppized.f90.229t.optimized:  vect__506.784_1887 = pow.simdclone.2 
(vect__1057.783_1889, { 
1.939999999999999946709294817992486059665679931640625e+0, 
1.939999999999999946709294817992486059665679931640625e+0 });
gasdev.fppized.f90.229t.optimized:  vect__66.139_93 = log.simdclone.0 
(vect__65.138_94);
lmd_swfrac.fppized.f90.229t.optimized:  vect__84.60_182 = exp.simdclone.0 
(vect__83.59_183);
lmd_swfrac.fppized.f90.229t.optimized:  vect__89.69_161 = exp.simdclone.0 
(vect__88.68_162);

and it also finishes successfully.

Question I have is about default search locations for the header file. On my 
machine I can
see:
access("/home/marxin/bin/gcc2/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/math-vector-fortran.h",
 R_OK) = -1 ENOENT (No such file or directory)
access("/home/marxin/bin/gcc2/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/../../../../x86_64-pc-linux-gnu/lib/x86_64-pc-linux-gnu/9.0.0/math-vector-fortran.h",
 R_OK) = -1 ENOENT (No such file or directory)
access("/home/marxin/bin/gcc2/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/../../../../x86_64-pc-linux-gnu/lib/../lib64/math-vector-fortran.h",
 R_OK) = -1 ENOENT (No such file or directory)
access("/home/marxin/bin/gcc2/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/../../../x86_64-pc-linux-gnu/9.0.0/math-vector-fortran.h",
 R_OK) = -1 ENOENT (No such file or directory)
access("/home/marxin/bin/gcc2/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/../../../../lib64/math-vector-fortran.h",
 R_OK) = -1 ENOENT (No such file or directory)
access("/lib/x86_64-pc-linux-gnu/9.0.0/math-vector-fortran.h", R_OK) = -1 
ENOENT (No such file or directory)
access("/lib/../lib64/math-vector-fortran.h", R_OK) = -1 ENOENT (No such file 
or directory)
access("/usr/lib/x86_64-pc-linux-gnu/9.0.0/math-vector-fortran.h", R_OK) = -1 
ENOENT (No such file or directory)
access("/usr/lib/../lib64/math-vector-fortran.h", R_OK) = -1 ENOENT (No such 
file or directory)
access("/home/marxin/bin/gcc2/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/../../../../x86_64-pc-linux-gnu/lib/math-vector-fortran.h",
 R_OK) = -1 ENOENT (No such file or directory)
access("/home/marxin/bin/gcc2/lib64/gcc/x86_64-pc-linux-gnu/9.0.0/../../../math-vector-fortran.h",
 R_OK) = -1 ENOENT (No such file or directory)
access("/lib/math-vector-fortran.h", R_OK) = -1 ENOENT (No such file or 
directory)
access("/usr/lib/math-vector-fortran.h", R_OK) = -1 ENOENT (No such file or 
directory)

Aren't these locations desired for libraries, instead of include locations?

Thoughts?
Thanks,
Martin

>From 53579915be2f2566d2bbf8ba52175762b8cea7ec Mon Sep 17 00:00:00 2001
From: marxin <mli...@suse.cz>
Date: Wed, 7 Nov 2018 12:41:19 +0100
Subject: [PATCH] Support simd function declarations via a pre-include.

gcc/ChangeLog:

2018-11-14  Martin Liska  <mli...@suse.cz>
	    Jakub Jelinek  <ja...@redhat.com>

	* config/gnu-user.h (TARGET_F951_NOSTDINC_OPTIONS): Define new
	macro.
	* gcc.c (find_fortran_header_file): New function.

gcc/fortran/ChangeLog:

2018-11-14  Martin Liska  <mli...@suse.cz>
	    Jakub Jelinek  <ja...@redhat.com>

	* decl.c (gfc_match_gcc_builtin): New function to
	find new !GCC attribute directive.
	* gfortran.h (gfc_adjust_builtins): Declre.
	* match.h (gfc_match_gcc_builtin): New function.
	* parse.c (decode_gcc_attribute): Parse "builtin" in
	GCC attributes.
	(parse_progunit): Modify builtins based on result of
	GCC builtin parsing.
	* scanner.c (load_file): Preinclude header if set
	by the flag_pre_include flag.
	* trans-intrinsic.c (add_simd_flag_for_built_in): New.
	(gfc_adjust_builtins): New.
---
 gcc/config/gnu-user.h         |  3 +++
 gcc/fortran/decl.c            | 33 +++++++++++++++++++++++++
 gcc/fortran/gfortran.h        |  2 ++
 gcc/fortran/lang-specs.h      |  8 +++++-
 gcc/fortran/lang.opt          |  4 +++
 gcc/fortran/match.h           |  1 +
 gcc/fortran/parse.c           |  3 +++
 gcc/fortran/scanner.c         | 10 ++++++++
 gcc/fortran/trans-intrinsic.c | 46 +++++++++++++++++++++++++++++++++++
 gcc/gcc.c                     | 19 +++++++++++++++
 10 files changed, 128 insertions(+), 1 deletion(-)

diff --git a/gcc/config/gnu-user.h b/gcc/config/gnu-user.h
index 5b48fb21514..f3ad7cf05fd 100644
--- a/gcc/config/gnu-user.h
+++ b/gcc/config/gnu-user.h
@@ -170,3 +170,6 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   LD_STATIC_OPTION " --whole-archive -llsan --no-whole-archive " \
   LD_DYNAMIC_OPTION "}}%{!static-liblsan:-llsan}"
 #endif
+
+#undef TARGET_F951_NOSTDINC_OPTIONS
+#define TARGET_F951_NOSTDINC_OPTIONS "%:fortran-header-file(-fpre-include= math-vector-fortran.h)"
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 2b77d950abb..938c35c508f 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;
 
+/* List middle-end built-ins that should be vectorized.  */
+vec<const char *> 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,33 @@ gfc_match_gcc_unroll (void)
   gfc_error ("Syntax error in !GCC$ UNROLL directive at %C");
   return MATCH_ERROR;
 }
+
+/* Match a !GCC$ builtin b attributes flags form:
+
+   The parameter b is name of a middle-end built-in.
+   Flags are one of:
+     - omp-simd-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_name (builtin) != MATCH_YES)
+    return MATCH_ERROR;
+
+  gfc_gobble_whitespace ();
+  if (gfc_match ("attributes") != MATCH_YES)
+    return MATCH_ERROR;
+
+  gfc_gobble_whitespace ();
+  if (gfc_match ("omp_simd_notinbranch") != MATCH_YES)
+    return MATCH_ERROR;
+
+  char *r = XNEWVEC (char, strlen (builtin) + 32);
+  sprintf (r, "__builtin_%s", builtin);
+  vectorized_builtins.safe_push (r);
+
+  return MATCH_YES;
+}
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index d8ef35d9d6c..bb7f4dd0c4b 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2763,6 +2763,7 @@ gfc_finalizer;
 bool gfc_in_match_data (void);
 match gfc_match_char_spec (gfc_typespec *);
 extern int directive_unroll;
+extern vec<const char *> vectorized_builtins;
 
 /* Handling Parameterized Derived Types  */
 bool gfc_insert_kind_parameter_exprs (gfc_expr *);
@@ -3501,5 +3502,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 c3ab9700ea7..6f940755801 100644
--- a/gcc/fortran/lang-specs.h
+++ b/gcc/fortran/lang-specs.h
@@ -32,8 +32,14 @@
 #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_NOSTDINC_OPTIONS
+#define TARGET_F951_NOSTDINC_OPTIONS
+#endif
+
 #define F951_OPTIONS        "%(cc1_options) %{J*} \
-			     %{!nostdinc:-fintrinsic-modules-path finclude%s}\
+			     %{!nostdinc:-fintrinsic-modules-path finclude%s " \
+			       TARGET_F951_NOSTDINC_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 2b7f2903761..a9eb58cbf23 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -662,6 +662,10 @@ fprotect-parens
 Fortran Var(flag_protect_parens) Init(-1)
 Protect parentheses in expressions.
 
+fpre-include=
+Fortran RejectNegative JoinedOrMissing 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 418542bd5a6..f25ed860c06 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 13cc6f5fccd..56d0d050bc3 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 55d6dafdb5d..cf56a675a08 100644
--- a/gcc/fortran/scanner.c
+++ b/gcc/fortran/scanner.c
@@ -2365,6 +2365,16 @@ load_file (const char *realfilename, const char *displayedname, bool initial)
 	    }
 	}
 
+      /* Make a guard to prevent recursive inclusion.  */
+      static bool preinclude_done = false;
+      if (!preinclude_done)
+	{
+	  preinclude_done = true;
+	  if (flag_pre_include != NULL && !load_file (flag_pre_include, NULL,
+						      false))
+	    exit (FATAL_EXIT_CODE);
+	}
+
       /* Preprocessed files have preprocessor lines added before the byte
          order mark, so first_line is not about the first line of the file
 	 but the first line that's not a preprocessor line.  */
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 4ae2b3252b5..40ff66663eb 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -597,7 +597,53 @@ 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 (fndecl == NULL_TREE)
+    return;
+
+  const char *name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
+  for (unsigned i = 0; i < vectorized_builtins.length (); i++)
+    if (strcmp (vectorized_builtins[i], name) == 0)
+      {
+	tree omp_clause = build_omp_clause (UNKNOWN_LOCATION,
+					    OMP_CLAUSE_NOTINBRANCH);
+	DECL_ATTRIBUTES (fndecl)
+	  = tree_cons (get_identifier ("omp declare simd"),
+		       build_tree_list (NULL_TREE, omp_clause),
+		       DECL_ATTRIBUTES (fndecl));
+	return;
+      }
+}
+
+/* Set SIMD attribute to all built-in functions that are mentioned
+   in 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);
+    }
+
+  vectorized_builtins.truncate (0);
+}
 
 /* Initialize function decls for library functions.  The external functions
    are created as required.  Builtin functions are added here.  */
diff --git a/gcc/gcc.c b/gcc/gcc.c
index c0d17eb4f1b..1b9370be1d4 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -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 *greater_than_spec_func (int, const char **);
 static const char *debug_level_greater_than_spec_func (int, const char **);
+static const char *find_fortran_header_file (int, const char **);
 static char *convert_white_space (char *);
 
 /* The Specs Language
@@ -1647,6 +1648,7 @@ static const struct spec_function static_spec_functions[] =
   { "replace-extension",	replace_extension_spec_func },
   { "gt",			greater_than_spec_func },
   { "debug-level-gt",		debug_level_greater_than_spec_func },
+  { "fortran-header-file",	find_fortran_header_file},
 #ifdef EXTRA_SPEC_FUNCTIONS
   EXTRA_SPEC_FUNCTIONS
 #endif
@@ -9889,6 +9891,23 @@ debug_level_greater_than_spec_func (int argc, const char **argv)
   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_header_file (int argc, const char **argv)
+{
+  if (argc != 2)
+    return NULL;
+
+  const char *path = find_file (argv[1]);
+  if (path != argv[1])
+      return concat (argv[0], path, NULL);
+
+  return NULL;
+}
+
+
 /* Insert backslash before spaces in ORIG (usually a file path), to 
    avoid being broken by spec parser.
 
-- 
2.19.1

Reply via email to