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" } }