On Thu, 12 Nov 2020, Jan Hubicka wrote: > Hi, > here is updated patch that replaces 'C' by '1'...'9' so we still have > place to specify size. > As discussed on IRC, this seems better alternative. > > Bootstrapped/regtested x86_64-linux, OK?
OK. Richard. > Honza > > gcc/ChangeLog: > > 2020-11-12 Jan Hubicka <hubi...@ucw.cz> > > * attr-fnspec.h: Update topleve comment. > (attr_fnspec::arg_direct_p): Accept 1...9. > (attr_fnspec::arg_maybe_written_p): Reject 1...9. > (attr_fnspec::arg_copied_to_arg_p): New member function. > * builtins.c (builtin_fnspec): Update fnspec of block copy. > * tree-ssa-alias.c (attr_fnspec::verify): Update. > > diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h > index 28135328437..766414a2520 100644 > --- a/gcc/attr-fnspec.h > +++ b/gcc/attr-fnspec.h > @@ -41,6 +41,9 @@ > written and does not escape > 'w' or 'W' specifies that the memory pointed to by the parameter does > not > escape > + '1'....'9' specifies that the memory pointed to by the parameter is > + copied to memory pointed to by different parameter > + (as in memcpy). > '.' specifies that nothing is known. > The uppercase letter in addition specifies that the memory pointed to > by the parameter is not dereferenced. For 'r' only read applies > @@ -51,8 +54,8 @@ > ' ' nothing is known > 't' the size of value written/read corresponds to the size of > of the pointed-to type of the argument type > - '1'...'9' the size of value written/read is given by the specified > - argument > + '1'...'9' specifies the size of value written/read is given by the > + specified argument > */ > > #ifndef ATTR_FNSPEC_H > @@ -122,7 +125,8 @@ public: > { > unsigned int idx = arg_idx (i); > gcc_checking_assert (arg_specified_p (i)); > - return str[idx] == 'R' || str[idx] == 'O' || str[idx] == 'W'; > + return str[idx] == 'R' || str[idx] == 'O' > + || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9'); > } > > /* True if argument is used. */ > @@ -161,6 +165,7 @@ public: > unsigned int idx = arg_idx (i); > gcc_checking_assert (arg_specified_p (i)); > return str[idx] != 'r' && str[idx] != 'R' > + && (str[idx] < '1' || str[idx] > '9') > && str[idx] != 'x' && str[idx] != 'X'; > } > > @@ -190,6 +195,21 @@ public: > return str[idx + 1] == 't'; > } > > + /* Return true if memory pointer to by argument is copied to a memory > + pointed to by a different argument (as in memcpy). > + In this case set ARG. */ > + bool > + arg_copied_to_arg_p (unsigned int i, unsigned int *arg) > + { > + unsigned int idx = arg_idx (i); > + gcc_checking_assert (arg_specified_p (i)); > + if (str[idx] < '1' || str[idx] > '9') > + return false; > + *arg = str[idx] - '1'; > + return true; > + } > + > + > /* True if the argument does not escape. */ > bool > arg_noescape_p (unsigned int i) > @@ -230,7 +250,7 @@ public: > return str[1] != 'c' && str[1] != 'C'; > } > > - /* Return true if all memory written by the function > + /* Return true if all memory written by the function > is specified by fnspec. */ > bool > global_memory_written_p () > diff --git a/gcc/builtins.c b/gcc/builtins.c > index da25343beb1..4ec1766cffd 100644 > --- a/gcc/builtins.c > +++ b/gcc/builtins.c > @@ -12939,16 +12939,16 @@ builtin_fnspec (tree callee) > argument. */ > case BUILT_IN_STRCAT: > case BUILT_IN_STRCAT_CHK: > - return "1cW R "; > + return "1cW 1 "; > case BUILT_IN_STRNCAT: > case BUILT_IN_STRNCAT_CHK: > - return "1cW R3"; > + return "1cW 13"; > case BUILT_IN_STRCPY: > case BUILT_IN_STRCPY_CHK: > - return "1cO R "; > + return "1cO 1 "; > case BUILT_IN_STPCPY: > case BUILT_IN_STPCPY_CHK: > - return ".cO R "; > + return ".cO 1 "; > case BUILT_IN_STRNCPY: > case BUILT_IN_MEMCPY: > case BUILT_IN_MEMMOVE: > @@ -12957,15 +12957,15 @@ builtin_fnspec (tree callee) > case BUILT_IN_STRNCPY_CHK: > case BUILT_IN_MEMCPY_CHK: > case BUILT_IN_MEMMOVE_CHK: > - return "1cO3R3"; > + return "1cO313"; > case BUILT_IN_MEMPCPY: > case BUILT_IN_MEMPCPY_CHK: > - return ".cO3R3"; > + return ".cO313"; > case BUILT_IN_STPNCPY: > case BUILT_IN_STPNCPY_CHK: > - return ".cO3R3"; > + return ".cO313"; > case BUILT_IN_BCOPY: > - return ".cR3O3"; > + return ".c23O3"; > case BUILT_IN_BZERO: > return ".cO2"; > case BUILT_IN_MEMCMP: > diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c > index e64011d04df..b1e8e5b5352 100644 > --- a/gcc/tree-ssa-alias.c > +++ b/gcc/tree-ssa-alias.c > @@ -3797,6 +3797,8 @@ attr_fnspec::verify () > default: > err = true; > } > + if (err) > + internal_error ("invalid fn spec attribute \"%s\"", str); > > /* Now check all parameters. */ > for (unsigned int i = 0; arg_specified_p (i); i++) > @@ -3813,21 +3815,28 @@ attr_fnspec::verify () > case 'w': > case 'W': > case '.': > + if ((str[idx + 1] >= '1' && str[idx + 1] <= '9') > + || str[idx + 1] == 't') > + { > + if (str[idx] != 'r' && str[idx] != 'R' > + && str[idx] != 'w' && str[idx] != 'W' > + && str[idx] != 'o' && str[idx] != 'O') > + err = true; > + if (str[idx] != 't' > + /* Size specified is scalar, so it should be described > + by ". " if specified at all. */ > + && (arg_specified_p (str[idx + 1] - '1') > + && str[arg_idx (str[idx + 1] - '1')] != '.')) > + err = true; > + } > + else if (str[idx + 1] != ' ') > + err = true; > break; > default: > - err = true; > + if (str[idx] < '1' || str[idx] > '9') > + err = true; > } > - if ((str[idx + 1] >= '1' && str[idx + 1] <= '9') > - || str[idx + 1] == 't') > - { > - if (str[idx] != 'r' && str[idx] != 'R' > - && str[idx] != 'w' && str[idx] != 'W' > - && str[idx] != 'o' && str[idx] != 'O') > - err = true; > - } > - else if (str[idx + 1] != ' ') > - err = true; > + if (err) > + internal_error ("invalid fn spec attribute \"%s\" arg %i", str, i); > } > - if (err) > - internal_error ("invalid fn spec attribute \"%s\"", str); > } > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg, Germany; GF: Felix Imend