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?

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')

Reply via email to