Hi All,

I took a few moments away from what I really must be doing to try out
an earlier version of the patch. There are quite a few CRs in the
patch and the third chunk in gcc.c was rejected, although I cannot see
why. I made a change to scanner.c to prevent the segfault that results
from not having the pre-include file in the right directory - see
attached.

Everything works fine with the testcases and a slightly evolved
version shows reasonable speed-ups:
program test_overloaded_intrinsic
  real(4) :: x4(3200), y4(3200, 10000)
  real(8) :: x8(3200), y8(3200)

   do i = 1,10000
    y4(:,i) = cos(x4)
    y4(:,i) = x4*y4(:,i)
    y4(:,i) = sqrt(y4(:,i))
  end do
  print *, y4(1,1)
end

Disappointingly, though, one of the worst cases in
https://www.fortran.uk/fortran-compiler-comparisons/ of a big
difference between gfortran and ifort with vectorization,
mp_prop_design.f90, doesn't seem to pick up any of the vectorization
opportunities, even though it is peppered with trig functions. Should
I be expecting this? Yes, I did add the other trig functions to the
pre-include file :-)

Best regards and thanks for taking care of this

Paul
On Fri, 16 Nov 2018 at 15:13, Martin Liška <mli...@suse.cz> wrote:
>
> On 11/16/18 2:49 PM, Jakub Jelinek wrote:
> > On Fri, Nov 16, 2018 at 02:24:42PM +0100, Martin Liška wrote:
> >> +  if (gfc_match (" (%n) attributes simd", builtin) != MATCH_YES)
> >> +    return MATCH_ERROR;
> >> +
> >> +  int builtin_kind = 0;
> >> +  if (gfc_match (" (notinbranch)") == MATCH_YES)
> >
> > I think you need " ( notinbranch )" here.
> >
> >> +    builtin_kind = -1;
> >> +  else if (gfc_match (" (inbranch)") == MATCH_YES)
> >> +    builtin_kind = 1;
> >
> > And similarly here (+ testsuite coverage for whether you can in free form
> > insert spaces in all the spots that should be allowed).
> > !gcc$ builtin ( sinf ) attributes simd ( notinbranch )  ! comment
> > e.g. should be valid in free form (and fixed form too).
> >
> >> --- a/gcc/fortran/gfortran.h
> >> +++ b/gcc/fortran/gfortran.h
> >> @@ -2764,6 +2764,18 @@ bool gfc_in_match_data (void);
> >>  match gfc_match_char_spec (gfc_typespec *);
> >>  extern int directive_unroll;
> >>
> >> +/* Tuple for parsing of vectorized built-ins.  */
> >> +struct vect_builtin_tuple
> >> +{
> >> +  vect_builtin_tuple (const char *n, int t): name (n), simd_type (t)
> >
> > gfc_vect_builtin_tuple ?
> > + document what the simd_type is (or make it enum or whatever).
> > One option would be enum omp_clause_code and use OMP_CLAUSE_ERROR for
> > the case where the argument isn't specified, but I think generally
> > gfortran.h doesn't depend on tree* stuff and wants to have its own
> > enums etc.
> >
> >> +extern vec<vect_builtin_tuple> vectorized_builtins;
> >
> > gfc_vectorized_builtins ?
> >
> >> --- a/gcc/fortran/trans-intrinsic.c
> >> +++ b/gcc/fortran/trans-intrinsic.c
> >> @@ -597,7 +597,61 @@ 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.  */
> >> +#include "print-tree.h"
> >
> > If you need to include a header, include it at the start of the file.
> >
> >> +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, name) == 0)
> >
> > How many add_simd_flag_for_built_in calls are we expecting and how many
> > vectorized_builtins.length ()?  If it is too much, perhaps e.g. sort
> > the vector by name and do a binary search.  At least if it turns out to be
> > non-trivial compile time.
> >> +
> >> +  vectorized_builtins.truncate (0);
> >
> > That is a memory leak, right?  The names are malloced.
> > And why truncate rather than release?
> >> +  const char *path = find_a_file (&include_prefixes, argv[1], R_OK, true);
> >> +  if (path != NULL)
> >> +      return concat (argv[0], path, NULL);
> >
> > Formatting.
> >> --- /dev/null
> >> +++ b/gcc/testsuite/gfortran.dg/simd-builtins-1.h
> >> @@ -0,0 +1,4 @@
> >> +!GCC$ builtin (sinf) attributes simd
> >> +!GCC$ builtin (sinf) attributes simd (inbranch)
> >> +!GCC$ builtin (sinf) attributes simd (notinbranch)
> >> +!GCC$ builtin (cosf) attributes simd (notinbranch)
> >
> > Are you sure it is a good idea to have the 3 first lines for the same
> > builtin, rather than different?
> >
> > It should be testsuite covered what we do in that case, but with the above
> > you don't cover what happens e.g. with notinbranch alone, or no argument.
> >
> > Plus, as I said, I think you should have one *.f and one *.f90 test where
> > you just use many of those !gcc$ builtin lines with spaces in various spots
> > to verify it is parsed properly.
> >
> >       Jakub
> >
>
> Hi.
>
> I'm sending version, I changed the container to hash_map that should provide
> faster look up.
>
> I've been testing the patch right now.
>
> Martin



-- 
"If you can't explain it simply, you don't understand it well enough"
- Albert Einstein
Index: gcc/config/gnu-user.h
===================================================================
*** gcc/config/gnu-user.h	(revision 266027)
--- gcc/config/gnu-user.h	(working copy)
*************** see the files COPYING3 and COPYING.RUNTI
*** 170,172 ****
--- 170,176 ----
    LD_STATIC_OPTION " --whole-archive -llsan --no-whole-archive " \
    LD_DYNAMIC_OPTION "}}%{!static-liblsan:-llsan}"
  #endif
+ 
+ #undef TARGET_F951_OPTIONS
+ #define TARGET_F951_OPTIONS "%{!nostdinc:\
+   %:fortran-preinclude-file(-fpre-include= math-vector-fortran.h)}"
Index: gcc/fortran/decl.c
===================================================================
*** gcc/fortran/decl.c	(revision 266027)
--- gcc/fortran/decl.c	(working copy)
*************** bool gfc_matching_function;
*** 98,103 ****
--- 98,106 ----
  /* 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<vect_builtin_tuple> 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;
*************** gfc_match_gcc_unroll (void)
*** 11243,11245 ****
--- 11246,11278 ----
    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;
+ 
+   int builtin_kind = 0;
+   if (gfc_match (" (notinbranch)") == MATCH_YES)
+     builtin_kind = -1;
+   else if (gfc_match (" (inbranch)") == MATCH_YES)
+     builtin_kind = 1;
+ 
+   char *r = XNEWVEC (char, strlen (builtin) + 32);
+   sprintf (r, "__builtin_%s", builtin);
+   vectorized_builtins.safe_push (vect_builtin_tuple (r, builtin_kind));
+ 
+   return MATCH_YES;
+ }
Index: gcc/fortran/gfortran.h
===================================================================
*** gcc/fortran/gfortran.h	(revision 266027)
--- gcc/fortran/gfortran.h	(working copy)
*************** bool gfc_in_match_data (void);
*** 2764,2769 ****
--- 2764,2781 ----
  match gfc_match_char_spec (gfc_typespec *);
  extern int directive_unroll;
  
+ /* Tuple for parsing of vectorized built-ins.  */
+ struct vect_builtin_tuple
+ {
+   vect_builtin_tuple (const char *n, int t): name (n), simd_type (t)
+   {}
+ 
+   const char *name;
+   int simd_type;
+ };
+ 
+ extern vec<vect_builtin_tuple> vectorized_builtins;
+ 
  /* Handling Parameterized Derived Types  */
  bool gfc_insert_kind_parameter_exprs (gfc_expr *);
  bool gfc_insert_parameter_exprs (gfc_expr *, gfc_actual_arglist *);
*************** bool gfc_is_reallocatable_lhs (gfc_expr
*** 3501,3505 ****
--- 3513,3518 ----
  /* trans-decl.c */
  
  void finish_oacc_declare (gfc_namespace *, gfc_symbol *, bool);
+ void gfc_adjust_builtins (void);
  
  #endif /* GCC_GFORTRAN_H  */
Index: gcc/fortran/lang-specs.h
===================================================================
*** gcc/fortran/lang-specs.h	(revision 266027)
--- gcc/fortran/lang-specs.h	(working copy)
***************
*** 32,40 ****
  #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 "}"
  #define F951_OPTIONS        "%(cc1_options) %{J*} \
! 			     %{!nostdinc:-fintrinsic-modules-path finclude%s}\
! 			     %{!fsyntax-only:%(invoke_as)}"
  #define F951_SOURCE_FORM    "%{!ffree-form:-ffixed-form}"
  
  
--- 32,46 ----
  #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}" \
! 			     TARGET_F951_OPTIONS \
! 			     "%{!fsyntax-only:%(invoke_as)}"
  #define F951_SOURCE_FORM    "%{!ffree-form:-ffixed-form}"
  
  
Index: gcc/fortran/lang.opt
===================================================================
*** gcc/fortran/lang.opt	(revision 266027)
--- gcc/fortran/lang.opt	(working copy)
*************** fprotect-parens
*** 662,667 ****
--- 662,671 ----
  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.
Index: gcc/fortran/match.h
===================================================================
*** gcc/fortran/match.h	(revision 266027)
--- gcc/fortran/match.h	(working copy)
*************** match gfc_match_dimension (void);
*** 247,252 ****
--- 247,253 ----
  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);
Index: gcc/fortran/parse.c
===================================================================
*** gcc/fortran/parse.c	(revision 266027)
--- gcc/fortran/parse.c	(working copy)
*************** decode_gcc_attribute (void)
*** 1072,1077 ****
--- 1072,1078 ----
  
    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.  */
*************** parse_progunit (gfc_statement st)
*** 5663,5668 ****
--- 5664,5671 ----
    gfc_state_data *p;
    int n;
  
+   gfc_adjust_builtins ();
+ 
    if (gfc_new_block
        && gfc_new_block->abr_modproc_decl
        && gfc_new_block->attr.function)
Index: gcc/fortran/scanner.c
===================================================================
*** gcc/fortran/scanner.c	(revision 266027)
--- gcc/fortran/scanner.c	(working copy)
*************** static locus gcc_attribute_locus;
*** 65,71 ****
  
  gfc_source_form gfc_current_form;
  static gfc_linebuf *line_head, *line_tail;
!        
  locus gfc_current_locus;
  const char *gfc_source_file;
  static FILE *gfc_src_file;
--- 65,71 ----
  
  gfc_source_form gfc_current_form;
  static gfc_linebuf *line_head, *line_tail;
! 
  locus gfc_current_locus;
  const char *gfc_source_file;
  static FILE *gfc_src_file;
*************** gfc_scanner_done_1 (void)
*** 282,300 ****
    gfc_linebuf *lb;
    gfc_file *f;
  
!   while(line_head != NULL) 
      {
        lb = line_head->next;
        free (line_head);
        line_head = lb;
      }
!      
!   while(file_head != NULL) 
      {
        f = file_head->next;
        free (file_head->filename);
        free (file_head);
!       file_head = f;    
      }
  }
  
--- 282,300 ----
    gfc_linebuf *lb;
    gfc_file *f;
  
!   while(line_head != NULL)
      {
        lb = line_head->next;
        free (line_head);
        line_head = lb;
      }
! 
!   while(file_head != NULL)
      {
        f = file_head->next;
        free (file_head->filename);
        free (file_head);
!       file_head = f;
      }
  }
  
*************** add_path_to_list (gfc_directorylist **li
*** 311,317 ****
    struct stat st;
    size_t len;
    int i;
!   
    p = path;
    while (*p == ' ' || *p == '\t')  /* someone might do "-I include" */
      if (*p++ == '\0')
--- 311,317 ----
    struct stat st;
    size_t len;
    int i;
! 
    p = path;
    while (*p == ' ' || *p == '\t')  /* someone might do "-I include" */
      if (*p++ == '\0')
*************** gfc_advance_line (void)
*** 581,591 ****
    if (gfc_at_end ())
      return;
  
!   if (gfc_current_locus.lb == NULL) 
      {
        end_flag = 1;
        return;
!     } 
  
    if (gfc_current_locus.lb->next
        && !gfc_current_locus.lb->next->dbg_emitted)
--- 581,591 ----
    if (gfc_at_end ())
      return;
  
!   if (gfc_current_locus.lb == NULL)
      {
        end_flag = 1;
        return;
!     }
  
    if (gfc_current_locus.lb->next
        && !gfc_current_locus.lb->next->dbg_emitted)
*************** gfc_advance_line (void)
*** 596,608 ****
  
    gfc_current_locus.lb = gfc_current_locus.lb->next;
  
!   if (gfc_current_locus.lb != NULL)	 
      gfc_current_locus.nextc = gfc_current_locus.lb->line;
!   else 
      {
        gfc_current_locus.nextc = NULL;
        end_flag = 1;
!     }       
  }
  
  
--- 596,608 ----
  
    gfc_current_locus.lb = gfc_current_locus.lb->next;
  
!   if (gfc_current_locus.lb != NULL)
      gfc_current_locus.nextc = gfc_current_locus.lb->line;
!   else
      {
        gfc_current_locus.nextc = NULL;
        end_flag = 1;
!     }
  }
  
  
*************** static gfc_char_t
*** 619,625 ****
  next_char (void)
  {
    gfc_char_t c;
!   
    if (gfc_current_locus.nextc == NULL)
      return '\n';
  
--- 619,625 ----
  next_char (void)
  {
    gfc_char_t c;
! 
    if (gfc_current_locus.nextc == NULL)
      return '\n';
  
*************** skip_free_oacc_sentinel (locus start, lo
*** 736,742 ****
  	      openacc_locus = old_loc;
  	      gfc_current_locus = start;
  	    }
! 	  else 
  	    r = false;
  	}
        else
--- 736,742 ----
  	      openacc_locus = old_loc;
  	      gfc_current_locus = start;
  	    }
! 	  else
  	    r = false;
  	}
        else
*************** skip_free_omp_sentinel (locus start, loc
*** 776,782 ****
  	      openmp_locus = old_loc;
  	      gfc_current_locus = start;
  	    }
! 	  else 
  	    r = false;
  	}
        else
--- 776,782 ----
  	      openmp_locus = old_loc;
  	      gfc_current_locus = start;
  	    }
! 	  else
  	    r = false;
  	}
        else
*************** skip_fixed_comments (void)
*** 1051,1057 ****
  	    }
  
  	  /* If -fopenmp/-fopenacc, we need to handle here 2 things:
! 	     1) don't treat !$omp/!$acc|c$omp/c$acc|*$omp / *$acc as comments, 
  		but directives
  	     2) handle OpenMP/OpenACC conditional compilation, where
  		!$|c$|*$ should be treated as 2 spaces if the characters
--- 1051,1057 ----
  	    }
  
  	  /* If -fopenmp/-fopenacc, we need to handle here 2 things:
! 	     1) don't treat !$omp/!$acc|c$omp/c$acc|*$omp / *$acc as comments,
  		but directives
  	     2) handle OpenMP/OpenACC conditional compilation, where
  		!$|c$|*$ should be treated as 2 spaces if the characters
*************** restart:
*** 1318,1324 ****
  	skip_comment_line ();
        else
  	gfc_advance_line ();
!       
        if (gfc_at_eof ())
  	goto not_continuation;
  
--- 1318,1324 ----
  	skip_comment_line ();
        else
  	gfc_advance_line ();
! 
        if (gfc_at_eof ())
  	goto not_continuation;
  
*************** restart:
*** 1421,1427 ****
  	    {
  	      gfc_current_locus.nextc--;
  	      if (warn_ampersand && in_string == INSTRING_WARN)
! 		gfc_warning (OPT_Wampersand, 
  			     "Missing %<&%> in continued character "
  			     "constant at %C");
  	    }
--- 1421,1427 ----
  	    {
  	      gfc_current_locus.nextc--;
  	      if (warn_ampersand && in_string == INSTRING_WARN)
! 		gfc_warning (OPT_Wampersand,
  			     "Missing %<&%> in continued character "
  			     "constant at %C");
  	    }
*************** gfc_gobble_whitespace (void)
*** 1732,1738 ****
     load_line returns whether the line was truncated.
  
     NOTE: The error machinery isn't available at this point, so we can't
! 	 easily report line and column numbers consistent with other 
  	 parts of gfortran.  */
  
  static int
--- 1732,1738 ----
     load_line returns whether the line was truncated.
  
     NOTE: The error machinery isn't available at this point, so we can't
! 	 easily report line and column numbers consistent with other
  	 parts of gfortran.  */
  
  static int
*************** load_line (FILE *input, gfc_char_t **pbu
*** 1788,1794 ****
        if (c == '\n')
  	{
  	  /* Check for illegal use of ampersand. See F95 Standard 3.3.1.3.  */
! 	  if (gfc_current_form == FORM_FREE 
  	      && !seen_printable && seen_ampersand)
  	    {
  	      if (pedantic)
--- 1788,1794 ----
        if (c == '\n')
  	{
  	  /* Check for illegal use of ampersand. See F95 Standard 3.3.1.3.  */
! 	  if (gfc_current_form == FORM_FREE
  	      && !seen_printable && seen_ampersand)
  	    {
  	      if (pedantic)
*************** include_line (gfc_char_t *line)
*** 2174,2180 ****
      c++;
  
    /* Find filename between quotes.  */
!   
    quote = *c++;
    if (quote != '"' && quote != '\'')
      return false;
--- 2174,2180 ----
      c++;
  
    /* Find filename between quotes.  */
! 
    quote = *c++;
    if (quote != '"' && quote != '\'')
      return false;
*************** include_line (gfc_char_t *line)
*** 2188,2194 ****
      return false;
  
    stop = c++;
!   
    while (*c == ' ' || *c == '\t')
      c++;
  
--- 2188,2194 ----
      return false;
  
    stop = c++;
! 
    while (*c == ' ' || *c == '\t')
      c++;
  
*************** load_file (const char *realfilename, con
*** 2261,2268 ****
        input = gfc_open_included_file (realfilename, false, false);
        if (input == NULL)
  	{
! 	  fprintf (stderr, "%s:%d: Error: Can't open included file '%s'\n",
! 		   current_file->filename, current_file->line, filename);
  	  return false;
  	}
        stat_result = stat (realfilename, &st);
--- 2261,2272 ----
        input = gfc_open_included_file (realfilename, false, false);
        if (input == NULL)
  	{
! 	  if (current_file)
! 	    fprintf (stderr, "%s:%d: Error: Can't open included file '%s'\n",
! 		     current_file->filename, current_file->line, filename);
! 	  else
! 	    fprintf (stderr, "Error: Can't open pre-included file '%s'\n",
! 		     filename);
  	  return false;
  	}
        stat_result = stat (realfilename, &st);
*************** gfc_new_file (void)
*** 2428,2433 ****
--- 2432,2441 ----
  {
    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);
Index: gcc/fortran/trans-intrinsic.c
===================================================================
*** gcc/fortran/trans-intrinsic.c	(revision 266027)
--- gcc/fortran/trans-intrinsic.c	(working copy)
*************** define_quad_builtin (const char *name, t
*** 597,603 ****
--- 597,657 ----
    return fndecl;
  }
  
+ /* Add SIMD attribute for FNDECL built-in if the built-in
+    name is in VECTORIZED_BUILTINS.  */
+ #include "print-tree.h"
+ 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, name) == 0)
+       {
+ 	int simd_type = vectorized_builtins[i].simd_type;
+ 	tree omp_clause = NULL_TREE;
+ 	if (simd_type == 0)
+ 	  ; /* No SIMD clause.  */
+ 	else
+ 	  {
+ 	    omp_clause_code code
+ 	      = (simd_type == 1 ? 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 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.  */
Index: gcc/gcc.c
===================================================================
*** gcc/gcc.c	(revision 266027)
--- gcc/gcc.c	(working copy)
*************** static const char *pass_through_libs_spe
*** 408,413 ****
--- 408,414 ----
  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_preinclude_file (int, const char **);
  static char *convert_white_space (char *);
  
  /* The Specs Language
*************** static const struct spec_function static
*** 1647,1652 ****
--- 1648,1654 ----
    { "replace-extension",	replace_extension_spec_func },
    { "gt",			greater_than_spec_func },
    { "debug-level-gt",		debug_level_greater_than_spec_func },
+   { "fortran-preinclude-file",	find_fortran_preinclude_file},
  #ifdef EXTRA_SPEC_FUNCTIONS
    EXTRA_SPEC_FUNCTIONS
  #endif
*************** do_spec_1 (const char *spec, int inswitc
*** 5948,5954 ****
  		     "%{foo=*:bar%*}%{foo=*:one%*two}"
  
  		   matches -foo=hello then it will produce:
! 		   
  		     barhello onehellotwo
  		*/
  		if (*p == 0 || *p == '}')
--- 5950,5956 ----
  		     "%{foo=*:bar%*}%{foo=*:one%*two}"
  
  		   matches -foo=hello then it will produce:
! 
  		     barhello onehellotwo
  		*/
  		if (*p == 0 || *p == '}')
*************** static unsigned HOST_WIDE_INT
*** 9585,9593 ****
  get_random_number (void)
  {
    unsigned HOST_WIDE_INT ret = 0;
!   int fd; 
  
!   fd = open ("/dev/urandom", O_RDONLY); 
    if (fd >= 0)
      {
        read (fd, &ret, sizeof (HOST_WIDE_INT));
--- 9587,9595 ----
  get_random_number (void)
  {
    unsigned HOST_WIDE_INT ret = 0;
!   int fd;
  
!   fd = open ("/dev/urandom", O_RDONLY);
    if (fd >= 0)
      {
        read (fd, &ret, sizeof (HOST_WIDE_INT));
*************** greater_than_spec_func (int argc, const
*** 9868,9873 ****
--- 9870,9892 ----
    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;
+ }
+ 
+ 
  /* Returns "" if debug_info_level is greater than ARGV[ARGC-1].
     Otherwise, return NULL.  */
  
*************** debug_level_greater_than_spec_func (int
*** 9889,9904 ****
    return NULL;
  }
  
! /* Insert backslash before spaces in ORIG (usually a file path), to 
     avoid being broken by spec parser.
  
     This function is needed as do_spec_1 treats white space (' ' and '\t')
     as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
     the file name should be treated as a single argument rather than being
!    broken into multiple. Solution is to insert '\\' before the space in a 
     file name.
!    
!    This function converts and only converts all occurrence of ' ' 
     to '\\' + ' ' and '\t' to '\\' + '\t'.  For example:
     "a b"  -> "a\\ b"
     "a  b" -> "a\\ \\ b"
--- 9908,9923 ----
    return NULL;
  }
  
! /* Insert backslash before spaces in ORIG (usually a file path), to
     avoid being broken by spec parser.
  
     This function is needed as do_spec_1 treats white space (' ' and '\t')
     as the end of an argument. But in case of -plugin /usr/gcc install/xxx.so,
     the file name should be treated as a single argument rather than being
!    broken into multiple. Solution is to insert '\\' before the space in a
     file name.
! 
!    This function converts and only converts all occurrence of ' '
     to '\\' + ' ' and '\t' to '\\' + '\t'.  For example:
     "a b"  -> "a\\ b"
     "a  b" -> "a\\ \\ b"
Index: gcc/testsuite/gfortran.dg/simd-builtins-1.f90
===================================================================
*** gcc/testsuite/gfortran.dg/simd-builtins-1.f90	(nonexistent)
--- gcc/testsuite/gfortran.dg/simd-builtins-1.f90	(working copy)
***************
*** 0 ****
--- 1,19 ----
+ ! { dg-do compile { target x86_64-*-linux* } }
+ ! { dg-additional-options "-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" } }
Index: gcc/testsuite/gfortran.dg/simd-builtins-1.h
===================================================================
*** gcc/testsuite/gfortran.dg/simd-builtins-1.h	(nonexistent)
--- gcc/testsuite/gfortran.dg/simd-builtins-1.h	(working copy)
***************
*** 0 ****
--- 1,4 ----
+ !GCC$ builtin (sinf) attributes simd
+ !GCC$ builtin (sinf) attributes simd (inbranch)
+ !GCC$ builtin (sinf) attributes simd (notinbranch)
+ !GCC$ builtin (cosf) attributes simd (notinbranch)
Index: gcc/testsuite/gfortran.dg/simd-builtins-2.f90
===================================================================
*** gcc/testsuite/gfortran.dg/simd-builtins-2.f90	(nonexistent)
--- gcc/testsuite/gfortran.dg/simd-builtins-2.f90	(working copy)
***************
*** 0 ****
--- 1,20 ----
+ ! { dg-do compile { target x86_64-*-linux* } }
+ ! { dg-additional-options "-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" } }

Reply via email to