Message ID | ZzdRWK0r3ft3T6hU@kam.mff.cuni.cz |
---|---|
State | New |
Headers | show |
Series | 'I' and 'U' fn spec specifiers | expand |
On Fri, 15 Nov 2024, Jan Hubicka wrote: > Hi, > To implement pointer parameters reproducible and unsequenced I would like to > use fnspec built at callgraph construction time. Pointer parameters are either > const or non-const. After discussion with Jens, I now understand that memory > pointed to by const pointers can only be read directly and not written to. > While parameters pointed to by normal pointers can be both read and written but > in a way that duplicated calls have no additional effect. > > I.e. > > int > test1 (int **a) [[reproducible]] > { > return **a; > } > is not valid, since it has double-indirection > > int > test2 (const int *a) [[reproducible]] > { > *(int *)a = 1 > } > > is not valid since the parmaeter is const > > int > test2 (int *a) [[reproducible]] > { > a[1] = a[0]; > } > > is valid. > > To represent the behaviour I need new fnspec specifiers. Our 'R' specifies > that parameter is readonly and only used directly, but also implies noescape > that is not promised by the standard. So I added 'I' (for input). To > represent that parameters is both read and written, but not directly I added > 'U' (for used). > > I am not 100% sure we want to go the fnspec path. It won't handle variadic > calls which I think are in general quite a minority though. > > Bootstrapped/regtested x86_64-linux with the rest of reproducible/unsequenced code. > Does it seem sane? fnspec was originally introduced for PTA, but 'I' and 'U' given the pointers escape, do not help PTA, as soon as pointers escape all (most) bets are lost. So where and how exactly do you plan to use those? They seems to be directed at redundancy elimination? Richard. > gcc/ChangeLog: > > * attr-fnspec.h: Add 'I' and 'U' specifiers. > (arg_direct_p): Use it. > * tree-ssa-alias.cc (attr_fnspec::verify): Accept 'I' and 'U'. > > diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h > index aef4701e6d1..4c332cb6c14 100644 > --- a/gcc/attr-fnspec.h > +++ b/gcc/attr-fnspec.h > @@ -41,6 +41,10 @@ > written and does not escape > 'w' or 'W' specifies that the memory pointed to by the parameter does not > escape > + 'I' specifies that parameter is only used read directly > + and *may* escape > + 'U' specifies that parameter is only used directly (read > + or written) and *may* escape > '1'....'9' specifies that the memory pointed to by the parameter is > copied to memory pointed to by different parameter > (as in memcpy). > @@ -125,8 +129,9 @@ public: > { > unsigned int idx = arg_idx (i); > gcc_checking_assert (arg_specified_p (i)); > - return str[idx] == 'R' || str[idx] == 'O' > - || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9'); > + return str[idx] == 'R' || str[idx] == 'O' || str[idx] == 'U' > + || str[idx] == 'I' || str[idx] == 'W' > + || (str[idx] >= '1' && str[idx] <= '9'); > } > > /* True if argument is used. */ > @@ -144,7 +149,8 @@ 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'); > + return str[idx] == 'r' || str[idx] == 'R' || str[idx] == 'I' > + || (str[idx] >= '1' && str[idx] <= '9'); > } > > /* True if memory reached by the argument is read (directly or indirectly) */ > diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc > index 8ad6a02ddc9..dca3b1cc721 100644 > --- a/gcc/tree-ssa-alias.cc > +++ b/gcc/tree-ssa-alias.cc > @@ -4138,6 +4138,8 @@ attr_fnspec::verify () > case 'O': > case 'w': > case 'W': > + case 'U': > + case 'I': > case '.': > if ((str[idx + 1] >= '1' && str[idx + 1] <= '9') > || str[idx + 1] == 't') >
Hello Richard, On Fri, 15 Nov 2024 15:00:44 +0100 (CET), Richard Biener wrote: > fnspec was originally introduced for PTA, but 'I' and 'U' given the > pointers escape, do not help PTA, as soon as pointers escape all > (most) bets are lost. > > So where and how exactly do you plan to use those? They seems to be > directed at redundancy elimination? During the discussion with Honza it occured to me that maybe gcc doesn't yet use the full potential of `restrict`-qualified pointers to `const`-qualified base. Thanks Jₑₙₛ
On Fri, 15 Nov 2024, Jₑₙₛ Gustedt wrote: > Hello Richard, > > On Fri, 15 Nov 2024 15:00:44 +0100 (CET), Richard Biener wrote: > > > fnspec was originally introduced for PTA, but 'I' and 'U' given the > > pointers escape, do not help PTA, as soon as pointers escape all > > (most) bets are lost. > > > > So where and how exactly do you plan to use those? They seems to be > > directed at redundancy elimination? > > During the discussion with Honza it occured to me that maybe gcc > doesn't yet use the full potential of `restrict`-qualified pointers to > `const`-qualified base. Could be - we have difficulties in applying 'restrict' to any pointer that's not the formal parameter of a function as the formal definition relies on properties of the language we cannot recover. Richard. > Thanks > Jₑₙₛ > > >
diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h index aef4701e6d1..4c332cb6c14 100644 --- a/gcc/attr-fnspec.h +++ b/gcc/attr-fnspec.h @@ -41,6 +41,10 @@ written and does not escape 'w' or 'W' specifies that the memory pointed to by the parameter does not escape + 'I' specifies that parameter is only used read directly + and *may* escape + 'U' specifies that parameter is only used directly (read + or written) and *may* escape '1'....'9' specifies that the memory pointed to by the parameter is copied to memory pointed to by different parameter (as in memcpy). @@ -125,8 +129,9 @@ public: { unsigned int idx = arg_idx (i); gcc_checking_assert (arg_specified_p (i)); - return str[idx] == 'R' || str[idx] == 'O' - || str[idx] == 'W' || (str[idx] >= '1' && str[idx] <= '9'); + return str[idx] == 'R' || str[idx] == 'O' || str[idx] == 'U' + || str[idx] == 'I' || str[idx] == 'W' + || (str[idx] >= '1' && str[idx] <= '9'); } /* True if argument is used. */ @@ -144,7 +149,8 @@ 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'); + return str[idx] == 'r' || str[idx] == 'R' || str[idx] == 'I' + || (str[idx] >= '1' && str[idx] <= '9'); } /* True if memory reached by the argument is read (directly or indirectly) */ diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc index 8ad6a02ddc9..dca3b1cc721 100644 --- a/gcc/tree-ssa-alias.cc +++ b/gcc/tree-ssa-alias.cc @@ -4138,6 +4138,8 @@ attr_fnspec::verify () case 'O': case 'w': case 'W': + case 'U': + case 'I': case '.': if ((str[idx + 1] >= '1' && str[idx + 1] <= '9') || str[idx + 1] == 't')