Hi,
ipa-reference, ipa-pure-const and ipa-modref could use the knowledge
about bulitins which is currently harwired into
ref_maybe_used_by_call_p_1, call_may_clobber_ref_p_1 and the PTA
computation.  This patch breaks out logic implemented in the first two
into a form of a simple descriptor that can be used by the IPA passes
(and other code).

I was considering an option of putting this into def file but I do not think
it is feasible without cluttering it quite a lot.

For ipa-modref I implemented dump informing about missing builtins. strlen,
sqrt and exp seems common offenders, but that can be handled incrementally
if the approach looks reasonable.
I would also look adding the description for PTA (perhaps with some
special cases remainig since it is more ad-hoc)

Bootstrapped/regtested x86_64-linux, OK?

gcc/ChangeLog:

2020-09-28  Jan Hubicka  <hubi...@ucw.cz>

        * tree-ssa-alias.c (ao_classify_builtin): New function commonizing
        logic from ...
        (ref_maybe_used_by_call_p_1): ... here.
        (call_may_clobber_ref_p_1): ... and here.
        * tree-ssa-alias.h (enum ao_function_flags): New enum.
        (struct ao_function_info): New structure.
        (ao_classify_builtin): Declare.

diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index 1dd02c0ea62..eecb8da6dd7 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -108,6 +108,33 @@ ao_ref::max_size_known_p () const
   return known_size_p (max_size);
 }
 
+/* Flags used in ao_function_info.  */
+
+enum ao_function_flags
+{
+  AO_FUNCTION_BARRIER = 1,
+  AO_FUNCTION_ERRNO = 2,
+};
+
+/* Describe side effects relevant for alias analysis of function call to
+   DECL.  */
+
+struct ao_function_info
+{
+  int num_param_reads;  /* Number of parameters function reads from,
+                          -1 if reads are unknown.  */
+  struct ao_access_info
+    {
+      char param;      /* Index of parameter read/written from.  */
+      char size_param; /* Index of parameter specifying size of the access,
+                          -1 if unknown.  */
+      char size;       /* Size of access if known, 0 if unknown.  */
+    } reads[2];
+  int num_param_writes;
+  struct ao_access_info writes[2];
+  enum ao_function_flags flags;
+};
+
 /* In tree-ssa-alias.c  */
 extern void ao_ref_init (ao_ref *, tree);
 extern void ao_ref_init_from_ptr_and_size (ao_ref *, tree, tree);
@@ -158,6 +185,7 @@ extern void debug (pt_solution *ptr);
 extern void dump_points_to_info_for (FILE *, tree);
 extern void debug_points_to_info_for (tree);
 extern void dump_alias_stats (FILE *);
+extern bool ao_classify_builtin (tree callee, ao_function_info *info);
 
 
 /* In tree-ssa-structalias.c  */
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index fe390d4ffbe..c182e7bb39c 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -2503,6 +2503,507 @@ modref_may_conflict (const gimple *stmt,
   return false;
 }
 
+/* If CALLEE has known side effects, fill in INFO and return true.
+   See tree-ssa-structalias.c:find_func_aliases
+   for the list of builtins we might need to handle here.  */
+
+bool
+ao_classify_builtin (tree callee, ao_function_info *info)
+{
+  built_in_function code = DECL_FUNCTION_CODE (callee);
+
+  switch (code)
+    {
+      /* All the following functions read memory pointed to by
+        their second argument and write memory pointed to by first
+        argument.
+        strcat/strncat additionally reads memory pointed to by the first
+        argument.  */
+      case BUILT_IN_STRCAT:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   2,                          /* num_param_reads.  */
+
+                   /* Reads and write descriptors are triples containing:
+                      - index of parameter read
+                      - index of parameter specifying access size
+                        (-1 if unknown)
+                      - access size in bytes (0 if unkown).  */
+
+                   {{0, -1, 0}, {1, -1, 0}},   /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STRNCAT:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   2,                          /* num_param_reads.  */
+                   {{0, -1, 0}, {1, 2, 0}},    /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STRCPY:
+      case BUILT_IN_STPCPY:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{1, -1, 0}},               /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STRNCPY:
+      case BUILT_IN_MEMCPY:
+      case BUILT_IN_MEMMOVE:
+      case BUILT_IN_MEMPCPY:
+      case BUILT_IN_STPNCPY:
+      case BUILT_IN_TM_MEMCPY:
+      case BUILT_IN_TM_MEMMOVE:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{1, 2, 0}},                /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, 2, 0}},                /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STRCAT_CHK:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   2,                          /* num_param_reads.  */
+                   {{0, -1, 0}, {1, -1, 0}},   /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STRNCAT_CHK:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   2,                          /* num_param_reads.  */
+                   {{0, -1, 0}, {1, 2, 0}},    /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STRCPY_CHK:
+      case BUILT_IN_STPCPY_CHK:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{1, -1, 0}},               /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STRNCPY_CHK:
+      case BUILT_IN_MEMCPY_CHK:
+      case BUILT_IN_MEMMOVE_CHK:
+      case BUILT_IN_MEMPCPY_CHK:
+      case BUILT_IN_STPNCPY_CHK:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{1, 2, 0}},                /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, 2, 0}},                /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_BCOPY:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{0, 2, 0}},                /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{1, 2, 0}},                /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+
+      /* The following functions read memory pointed to by their
+        first argument.  */
+      CASE_BUILT_IN_TM_LOAD (1):
+      CASE_BUILT_IN_TM_LOAD (2):
+      CASE_BUILT_IN_TM_LOAD (4):
+      CASE_BUILT_IN_TM_LOAD (8):
+      CASE_BUILT_IN_TM_LOAD (FLOAT):
+      CASE_BUILT_IN_TM_LOAD (DOUBLE):
+      CASE_BUILT_IN_TM_LOAD (LDOUBLE):
+      CASE_BUILT_IN_TM_LOAD (M64):
+      CASE_BUILT_IN_TM_LOAD (M128):
+      CASE_BUILT_IN_TM_LOAD (M256):
+      case BUILT_IN_TM_LOG:
+      case BUILT_IN_TM_LOG_1:
+      case BUILT_IN_TM_LOG_2:
+      case BUILT_IN_TM_LOG_4:
+      case BUILT_IN_TM_LOG_8:
+      case BUILT_IN_TM_LOG_FLOAT:
+      case BUILT_IN_TM_LOG_DOUBLE:
+      case BUILT_IN_TM_LOG_LDOUBLE:
+      case BUILT_IN_TM_LOG_M64:
+      case BUILT_IN_TM_LOG_M128:
+      case BUILT_IN_TM_LOG_M256:
+
+      case BUILT_IN_INDEX:
+      case BUILT_IN_STRCHR:
+      case BUILT_IN_STRRCHR:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   /* TODO: For TM builtins size is known.  */
+                   {{0, -1, 0}},               /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+
+      /* These read memory pointed to by the first argument.
+        Allocating memory does not have any side-effects apart from
+        being the definition point for the pointer.
+        Unix98 specifies that errno is set on allocation failure.  */
+      case BUILT_IN_STRDUP:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{0, -1, 0}},               /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   AO_FUNCTION_ERRNO,          /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STRNDUP:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{0, 1, 0}},                /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   AO_FUNCTION_ERRNO,          /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      /* Allocating memory does not have any side-effects apart from
+        being the definition point for the pointer.  */
+      case BUILT_IN_MALLOC:
+      case BUILT_IN_ALIGNED_ALLOC:
+      case BUILT_IN_CALLOC:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   AO_FUNCTION_ERRNO,          /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      /* These read memory pointed to by the first argument with size
+        in the third argument.  */
+      case BUILT_IN_MEMCHR:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{0, 2, 0}},                /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      /* These read memory pointed to by the first and second arguments.  */
+      case BUILT_IN_STRSTR:
+      case BUILT_IN_STRPBRK:
+       {
+         static struct ao_function_info ret_info
+              = {
+                   2,                          /* num_param_reads.  */
+                   {{0, -1, 0}, {1, -1, 0}},   /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      /* Freeing memory kills the pointed-to memory.  More importantly
+        the call has to serve as a barrier for moving loads and stores
+        across it.  */
+      case BUILT_IN_FREE:
+      case BUILT_IN_VA_END:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      /* Realloc serves both as allocation point and deallocation point.  */
+      case BUILT_IN_REALLOC:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   1,                          /* num_param_reads.  */
+                   {{0, 1, 0}},                /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   AO_FUNCTION_ERRNO,          /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_GAMMA_R:
+      case BUILT_IN_GAMMAF_R:
+      case BUILT_IN_GAMMAL_R:
+      case BUILT_IN_LGAMMA_R:
+      case BUILT_IN_LGAMMAF_R:
+      case BUILT_IN_LGAMMAL_R:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{1, -1, 0}},               /* Param written.  */
+                   AO_FUNCTION_ERRNO,          /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_FREXP:
+      case BUILT_IN_FREXPF:
+      case BUILT_IN_FREXPL:
+      case BUILT_IN_MODF:
+      case BUILT_IN_MODFF:
+      case BUILT_IN_MODFL:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{1, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_REMQUO:
+      case BUILT_IN_REMQUOF:
+      case BUILT_IN_REMQUOL:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{2, -1, 0}},               /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_SINCOS:
+      case BUILT_IN_SINCOSF:
+      case BUILT_IN_SINCOSL:
+       {
+         static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {{1, -1, 0}, {2, -1, 0}},   /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         tree type = float_ptr_type_node;
+         if (code == BUILT_IN_SINCOS)
+           type = double_ptr_type_node;
+         else
+           type = long_double_ptr_type_node;
+         ret_info.writes[0].size = ret_info.writes[1].size
+                = tree_to_uhwi (TYPE_SIZE_UNIT (type));
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_MEMSET:
+      case BUILT_IN_MEMSET_CHK:
+      case BUILT_IN_TM_MEMSET:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   {0, 2, 0},                  /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      CASE_BUILT_IN_TM_STORE (1):
+      CASE_BUILT_IN_TM_STORE (2):
+      CASE_BUILT_IN_TM_STORE (4):
+      CASE_BUILT_IN_TM_STORE (8):
+      CASE_BUILT_IN_TM_STORE (FLOAT):
+      CASE_BUILT_IN_TM_STORE (DOUBLE):
+      CASE_BUILT_IN_TM_STORE (LDOUBLE):
+      CASE_BUILT_IN_TM_STORE (M64):
+      CASE_BUILT_IN_TM_STORE (M128):
+      CASE_BUILT_IN_TM_STORE (M256):
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   1,                          /* num_param_writes.  */
+                   /* TODO: Size is known.  */
+                   {0, -1, 0},                 /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      case BUILT_IN_STACK_SAVE:
+      CASE_BUILT_IN_ALLOCA:
+      case BUILT_IN_ASSUME_ALIGNED:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      /* But posix_memalign stores a pointer into the memory pointed to
+        by its first argument.  */
+      case BUILT_IN_POSIX_MEMALIGN:
+       {
+         static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {{0, -1, 0}},               /* Param written.  */
+                   AO_FUNCTION_ERRNO,          /* flags.  */
+                };
+         ret_info.writes[0].size
+                = tree_to_uhwi (TYPE_SIZE_UNIT (ptr_type_node));
+         *info = ret_info;
+         return true;
+       }
+      /* The following builtins do not read from memory.  */
+      case BUILT_IN_STACK_RESTORE:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   0,                          /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   0,                          /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   (ao_function_flags)0,       /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+      /* __sync_* builtins and some OpenMP builtins act as threading
+        barriers.  */
+#undef DEF_SYNC_BUILTIN
+#define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
+#include "sync-builtins.def"
+#undef DEF_SYNC_BUILTIN
+      case BUILT_IN_GOMP_ATOMIC_START:
+      case BUILT_IN_GOMP_ATOMIC_END:
+      case BUILT_IN_GOMP_BARRIER:
+      case BUILT_IN_GOMP_BARRIER_CANCEL:
+      case BUILT_IN_GOMP_TASKWAIT:
+      case BUILT_IN_GOMP_TASKGROUP_END:
+      case BUILT_IN_GOMP_CRITICAL_START:
+      case BUILT_IN_GOMP_CRITICAL_END:
+      case BUILT_IN_GOMP_CRITICAL_NAME_START:
+      case BUILT_IN_GOMP_CRITICAL_NAME_END:
+      case BUILT_IN_GOMP_LOOP_END:
+      case BUILT_IN_GOMP_LOOP_END_CANCEL:
+      case BUILT_IN_GOMP_ORDERED_START:
+      case BUILT_IN_GOMP_ORDERED_END:
+      case BUILT_IN_GOMP_SECTIONS_END:
+      case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
+      case BUILT_IN_GOMP_SINGLE_COPY_START:
+      case BUILT_IN_GOMP_SINGLE_COPY_END:
+       {
+         const static struct ao_function_info ret_info
+              = {
+                   -1,                         /* num_param_reads.  */
+                   {},                         /* Param read.  */
+                   -1,                         /* num_param_writes.  */
+                   {},                         /* Param written.  */
+                   AO_FUNCTION_BARRIER,        /* flags.  */
+                };
+         *info = ret_info;
+         return true;
+       }
+
+      default:
+       return false;
+    }
+}
+
 /* If the call CALL may use the memory reference REF return true,
    otherwise return false.  */
 
@@ -2574,219 +3075,37 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *ref, 
bool tbaa_p)
   /* Handle those builtin functions explicitly that do not act as
      escape points.  See tree-ssa-structalias.c:find_func_aliases
      for the list of builtins we might need to handle here.  */
+  struct ao_function_info info;
   if (callee != NULL_TREE
-      && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
-    switch (DECL_FUNCTION_CODE (callee))
-      {
-       /* All the following functions read memory pointed to by
-          their second argument.  strcat/strncat additionally
-          reads memory pointed to by the first argument.  */
-       case BUILT_IN_STRCAT:
-       case BUILT_IN_STRNCAT:
-         {
-           ao_ref dref;
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          NULL_TREE);
-           if (refs_may_alias_p_1 (&dref, ref, false))
-             return true;
-         }
-         /* FALLTHRU */
-       case BUILT_IN_STRCPY:
-       case BUILT_IN_STRNCPY:
-       case BUILT_IN_MEMCPY:
-       case BUILT_IN_MEMMOVE:
-       case BUILT_IN_MEMPCPY:
-       case BUILT_IN_STPCPY:
-       case BUILT_IN_STPNCPY:
-       case BUILT_IN_TM_MEMCPY:
-       case BUILT_IN_TM_MEMMOVE:
-         {
-           ao_ref dref;
-           tree size = NULL_TREE;
-           if (gimple_call_num_args (call) == 3)
-             size = gimple_call_arg (call, 2);
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 1),
-                                          size);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-       case BUILT_IN_STRCAT_CHK:
-       case BUILT_IN_STRNCAT_CHK:
-         {
-           ao_ref dref;
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          NULL_TREE);
-           if (refs_may_alias_p_1 (&dref, ref, false))
-             return true;
-         }
-         /* FALLTHRU */
-       case BUILT_IN_STRCPY_CHK:
-       case BUILT_IN_STRNCPY_CHK:
-       case BUILT_IN_MEMCPY_CHK:
-       case BUILT_IN_MEMMOVE_CHK:
-       case BUILT_IN_MEMPCPY_CHK:
-       case BUILT_IN_STPCPY_CHK:
-       case BUILT_IN_STPNCPY_CHK:
-         {
-           ao_ref dref;
-           tree size = NULL_TREE;
-           if (gimple_call_num_args (call) == 4)
-             size = gimple_call_arg (call, 2);
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 1),
-                                          size);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-       case BUILT_IN_BCOPY:
-         {
-           ao_ref dref;
-           tree size = gimple_call_arg (call, 2);
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          size);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-
-       /* The following functions read memory pointed to by their
-          first argument.  */
-       CASE_BUILT_IN_TM_LOAD (1):
-       CASE_BUILT_IN_TM_LOAD (2):
-       CASE_BUILT_IN_TM_LOAD (4):
-       CASE_BUILT_IN_TM_LOAD (8):
-       CASE_BUILT_IN_TM_LOAD (FLOAT):
-       CASE_BUILT_IN_TM_LOAD (DOUBLE):
-       CASE_BUILT_IN_TM_LOAD (LDOUBLE):
-       CASE_BUILT_IN_TM_LOAD (M64):
-       CASE_BUILT_IN_TM_LOAD (M128):
-       CASE_BUILT_IN_TM_LOAD (M256):
-       case BUILT_IN_TM_LOG:
-       case BUILT_IN_TM_LOG_1:
-       case BUILT_IN_TM_LOG_2:
-       case BUILT_IN_TM_LOG_4:
-       case BUILT_IN_TM_LOG_8:
-       case BUILT_IN_TM_LOG_FLOAT:
-       case BUILT_IN_TM_LOG_DOUBLE:
-       case BUILT_IN_TM_LOG_LDOUBLE:
-       case BUILT_IN_TM_LOG_M64:
-       case BUILT_IN_TM_LOG_M128:
-       case BUILT_IN_TM_LOG_M256:
-         return ptr_deref_may_alias_ref_p_1 (gimple_call_arg (call, 0), ref);
-
-       /* These read memory pointed to by the first argument.  */
-       case BUILT_IN_STRDUP:
-       case BUILT_IN_STRNDUP:
-       case BUILT_IN_REALLOC:
-         {
-           ao_ref dref;
-           tree size = NULL_TREE;
-           if (gimple_call_num_args (call) == 2)
-             size = gimple_call_arg (call, 1);
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          size);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-       /* These read memory pointed to by the first argument.  */
-       case BUILT_IN_INDEX:
-       case BUILT_IN_STRCHR:
-       case BUILT_IN_STRRCHR:
-         {
-           ao_ref dref;
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          NULL_TREE);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-       /* These read memory pointed to by the first argument with size
-          in the third argument.  */
-       case BUILT_IN_MEMCHR:
-         {
-           ao_ref dref;
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          gimple_call_arg (call, 2));
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-       /* These read memory pointed to by the first and second arguments.  */
-       case BUILT_IN_STRSTR:
-       case BUILT_IN_STRPBRK:
-         {
-           ao_ref dref;
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          NULL_TREE);
-           if (refs_may_alias_p_1 (&dref, ref, false))
-             return true;
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 1),
-                                          NULL_TREE);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-
-       /* The following builtins do not read from memory.  */
-       case BUILT_IN_FREE:
-       case BUILT_IN_MALLOC:
-       case BUILT_IN_POSIX_MEMALIGN:
-       case BUILT_IN_ALIGNED_ALLOC:
-       case BUILT_IN_CALLOC:
-       CASE_BUILT_IN_ALLOCA:
-       case BUILT_IN_STACK_SAVE:
-       case BUILT_IN_STACK_RESTORE:
-       case BUILT_IN_MEMSET:
-       case BUILT_IN_TM_MEMSET:
-       case BUILT_IN_MEMSET_CHK:
-       case BUILT_IN_FREXP:
-       case BUILT_IN_FREXPF:
-       case BUILT_IN_FREXPL:
-       case BUILT_IN_GAMMA_R:
-       case BUILT_IN_GAMMAF_R:
-       case BUILT_IN_GAMMAL_R:
-       case BUILT_IN_LGAMMA_R:
-       case BUILT_IN_LGAMMAF_R:
-       case BUILT_IN_LGAMMAL_R:
-       case BUILT_IN_MODF:
-       case BUILT_IN_MODFF:
-       case BUILT_IN_MODFL:
-       case BUILT_IN_REMQUO:
-       case BUILT_IN_REMQUOF:
-       case BUILT_IN_REMQUOL:
-       case BUILT_IN_SINCOS:
-       case BUILT_IN_SINCOSF:
-       case BUILT_IN_SINCOSL:
-       case BUILT_IN_ASSUME_ALIGNED:
-       case BUILT_IN_VA_END:
+      && gimple_call_builtin_p (call, BUILT_IN_NORMAL)
+      && (ao_classify_builtin (callee, &info)))
+    {
+      if (info.flags & AO_FUNCTION_BARRIER)
+       return true;
+      if (info.num_param_reads >= 0)
+       {
+         for (int i = 0; i < info.num_param_reads; i++)
+           {
+             ao_ref dref;
+             tree size = NULL_TREE;
+
+             gcc_checking_assert (info.reads[i].size_param
+                                  != info.reads[i].param);
+             if (info.reads[i].size_param != -1)
+               size = gimple_call_arg (call, info.reads[i].size);
+             else if (info.reads[i].size)
+               size = build_int_cst (size_type_node, info.reads[i].size);
+             ao_ref_init_from_ptr_and_size (&dref,
+                                            gimple_call_arg
+                                                (call,
+                                                 info.reads[i].param),
+                                            size);
+             if (refs_may_alias_p_1 (&dref, ref, tbaa_p))
+               return true;
+           }
          return false;
-       /* __sync_* builtins and some OpenMP builtins act as threading
-          barriers.  */
-#undef DEF_SYNC_BUILTIN
-#define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
-#include "sync-builtins.def"
-#undef DEF_SYNC_BUILTIN
-       case BUILT_IN_GOMP_ATOMIC_START:
-       case BUILT_IN_GOMP_ATOMIC_END:
-       case BUILT_IN_GOMP_BARRIER:
-       case BUILT_IN_GOMP_BARRIER_CANCEL:
-       case BUILT_IN_GOMP_TASKWAIT:
-       case BUILT_IN_GOMP_TASKGROUP_END:
-       case BUILT_IN_GOMP_CRITICAL_START:
-       case BUILT_IN_GOMP_CRITICAL_END:
-       case BUILT_IN_GOMP_CRITICAL_NAME_START:
-       case BUILT_IN_GOMP_CRITICAL_NAME_END:
-       case BUILT_IN_GOMP_LOOP_END:
-       case BUILT_IN_GOMP_LOOP_END_CANCEL:
-       case BUILT_IN_GOMP_ORDERED_START:
-       case BUILT_IN_GOMP_ORDERED_END:
-       case BUILT_IN_GOMP_SECTIONS_END:
-       case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
-       case BUILT_IN_GOMP_SINGLE_COPY_START:
-       case BUILT_IN_GOMP_SINGLE_COPY_END:
-         return true;
-
-       default:
-         /* Fallthru to general call handling.  */;
-      }
+       }
+    }
 
   /* Check if base is a global static variable that is not read
      by the function.  */
@@ -2961,7 +3280,9 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, bool 
tbaa_p)
          modref_summary *summary = get_modref_function_summary (node);
          if (summary)
            {
-             if (!modref_may_conflict (call, summary->stores, ref, tbaa_p))
+             if (!modref_may_conflict (call, summary->stores, ref, tbaa_p)
+                 && (!summary->writes_errno
+                     || !targetm.ref_may_alias_errno (ref)))
                {
                  alias_stats.modref_clobber_no_alias++;
                  if (dump_file && (dump_flags & TDF_DETAILS))
@@ -3016,205 +3337,43 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref, 
bool tbaa_p)
       && SSA_NAME_POINTS_TO_READONLY_MEMORY (TREE_OPERAND (base, 0)))
     return false;
 
+  struct ao_function_info info;
   /* Handle those builtin functions explicitly that do not act as
-     escape points.  See tree-ssa-structalias.c:find_func_aliases
-     for the list of builtins we might need to handle here.  */
+     escape points.  */
   if (callee != NULL_TREE
-      && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
-    switch (DECL_FUNCTION_CODE (callee))
-      {
-       /* All the following functions clobber memory pointed to by
-          their first argument.  */
-       case BUILT_IN_STRCPY:
-       case BUILT_IN_STRNCPY:
-       case BUILT_IN_MEMCPY:
-       case BUILT_IN_MEMMOVE:
-       case BUILT_IN_MEMPCPY:
-       case BUILT_IN_STPCPY:
-       case BUILT_IN_STPNCPY:
-       case BUILT_IN_STRCAT:
-       case BUILT_IN_STRNCAT:
-       case BUILT_IN_MEMSET:
-       case BUILT_IN_TM_MEMSET:
-       CASE_BUILT_IN_TM_STORE (1):
-       CASE_BUILT_IN_TM_STORE (2):
-       CASE_BUILT_IN_TM_STORE (4):
-       CASE_BUILT_IN_TM_STORE (8):
-       CASE_BUILT_IN_TM_STORE (FLOAT):
-       CASE_BUILT_IN_TM_STORE (DOUBLE):
-       CASE_BUILT_IN_TM_STORE (LDOUBLE):
-       CASE_BUILT_IN_TM_STORE (M64):
-       CASE_BUILT_IN_TM_STORE (M128):
-       CASE_BUILT_IN_TM_STORE (M256):
-       case BUILT_IN_TM_MEMCPY:
-       case BUILT_IN_TM_MEMMOVE:
-         {
-           ao_ref dref;
-           tree size = NULL_TREE;
-           /* Don't pass in size for strncat, as the maximum size
-              is strlen (dest) + n + 1 instead of n, resp.
-              n + 1 at dest + strlen (dest), but strlen (dest) isn't
-              known.  */
-           if (gimple_call_num_args (call) == 3
-               && DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT)
-             size = gimple_call_arg (call, 2);
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          size);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-       case BUILT_IN_STRCPY_CHK:
-       case BUILT_IN_STRNCPY_CHK:
-       case BUILT_IN_MEMCPY_CHK:
-       case BUILT_IN_MEMMOVE_CHK:
-       case BUILT_IN_MEMPCPY_CHK:
-       case BUILT_IN_STPCPY_CHK:
-       case BUILT_IN_STPNCPY_CHK:
-       case BUILT_IN_STRCAT_CHK:
-       case BUILT_IN_STRNCAT_CHK:
-       case BUILT_IN_MEMSET_CHK:
-         {
-           ao_ref dref;
-           tree size = NULL_TREE;
-           /* Don't pass in size for __strncat_chk, as the maximum size
-              is strlen (dest) + n + 1 instead of n, resp.
-              n + 1 at dest + strlen (dest), but strlen (dest) isn't
-              known.  */
-           if (gimple_call_num_args (call) == 4
-               && DECL_FUNCTION_CODE (callee) != BUILT_IN_STRNCAT_CHK)
-             size = gimple_call_arg (call, 2);
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 0),
-                                          size);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-       case BUILT_IN_BCOPY:
-         {
-           ao_ref dref;
-           tree size = gimple_call_arg (call, 2);
-           ao_ref_init_from_ptr_and_size (&dref,
-                                          gimple_call_arg (call, 1),
-                                          size);
-           return refs_may_alias_p_1 (&dref, ref, false);
-         }
-       /* Allocating memory does not have any side-effects apart from
-          being the definition point for the pointer.  */
-       case BUILT_IN_MALLOC:
-       case BUILT_IN_ALIGNED_ALLOC:
-       case BUILT_IN_CALLOC:
-       case BUILT_IN_STRDUP:
-       case BUILT_IN_STRNDUP:
-         /* Unix98 specifies that errno is set on allocation failure.  */
-         if (flag_errno_math
-             && targetm.ref_may_alias_errno (ref))
-           return true;
-         return false;
-       case BUILT_IN_STACK_SAVE:
-       CASE_BUILT_IN_ALLOCA:
-       case BUILT_IN_ASSUME_ALIGNED:
+      && gimple_call_builtin_p (call, BUILT_IN_NORMAL)
+      && (ao_classify_builtin (callee, &info)))
+    {
+      if (info.flags & AO_FUNCTION_BARRIER)
+       return true;
+      if ((info.flags & AO_FUNCTION_ERRNO)
+         && flag_errno_math
+         && targetm.ref_may_alias_errno (ref))
+       return true;
+      if (info.num_param_writes >= 0)
+       {
+         for (int i = 0; i < info.num_param_writes; i++)
+           {
+             ao_ref dref;
+             tree size = NULL_TREE;
+
+             gcc_checking_assert (info.writes[i].size_param
+                                  != info.writes[i].param);
+             if (info.writes[i].size_param != -1)
+               size = gimple_call_arg (call, info.writes[i].size_param);
+             else if (info.writes[i].size)
+               size = build_int_cst (size_type_node, info.writes[i].size);
+             ao_ref_init_from_ptr_and_size (&dref,
+                                            gimple_call_arg
+                                                (call,
+                                                 info.writes[i].param),
+                                            size);
+             if (refs_may_alias_p_1 (&dref, ref, tbaa_p))
+               return true;
+           }
          return false;
-       /* But posix_memalign stores a pointer into the memory pointed to
-          by its first argument.  */
-       case BUILT_IN_POSIX_MEMALIGN:
-         {
-           tree ptrptr = gimple_call_arg (call, 0);
-           ao_ref dref;
-           ao_ref_init_from_ptr_and_size (&dref, ptrptr,
-                                          TYPE_SIZE_UNIT (ptr_type_node));
-           return (refs_may_alias_p_1 (&dref, ref, false)
-                   || (flag_errno_math
-                       && targetm.ref_may_alias_errno (ref)));
-         }
-       /* Freeing memory kills the pointed-to memory.  More importantly
-          the call has to serve as a barrier for moving loads and stores
-          across it.  */
-       case BUILT_IN_FREE:
-       case BUILT_IN_VA_END:
-         {
-           tree ptr = gimple_call_arg (call, 0);
-           return ptr_deref_may_alias_ref_p_1 (ptr, ref);
-         }
-       /* Realloc serves both as allocation point and deallocation point.  */
-       case BUILT_IN_REALLOC:
-         {
-           tree ptr = gimple_call_arg (call, 0);
-           /* Unix98 specifies that errno is set on allocation failure.  */
-           return ((flag_errno_math
-                    && targetm.ref_may_alias_errno (ref))
-                   || ptr_deref_may_alias_ref_p_1 (ptr, ref));
-         }
-       case BUILT_IN_GAMMA_R:
-       case BUILT_IN_GAMMAF_R:
-       case BUILT_IN_GAMMAL_R:
-       case BUILT_IN_LGAMMA_R:
-       case BUILT_IN_LGAMMAF_R:
-       case BUILT_IN_LGAMMAL_R:
-         {
-           tree out = gimple_call_arg (call, 1);
-           if (ptr_deref_may_alias_ref_p_1 (out, ref))
-             return true;
-           if (flag_errno_math)
-             break;
-           return false;
-         }
-       case BUILT_IN_FREXP:
-       case BUILT_IN_FREXPF:
-       case BUILT_IN_FREXPL:
-       case BUILT_IN_MODF:
-       case BUILT_IN_MODFF:
-       case BUILT_IN_MODFL:
-         {
-           tree out = gimple_call_arg (call, 1);
-           return ptr_deref_may_alias_ref_p_1 (out, ref);
-         }
-       case BUILT_IN_REMQUO:
-       case BUILT_IN_REMQUOF:
-       case BUILT_IN_REMQUOL:
-         {
-           tree out = gimple_call_arg (call, 2);
-           if (ptr_deref_may_alias_ref_p_1 (out, ref))
-             return true;
-           if (flag_errno_math)
-             break;
-           return false;
-         }
-       case BUILT_IN_SINCOS:
-       case BUILT_IN_SINCOSF:
-       case BUILT_IN_SINCOSL:
-         {
-           tree sin = gimple_call_arg (call, 1);
-           tree cos = gimple_call_arg (call, 2);
-           return (ptr_deref_may_alias_ref_p_1 (sin, ref)
-                   || ptr_deref_may_alias_ref_p_1 (cos, ref));
-         }
-       /* __sync_* builtins and some OpenMP builtins act as threading
-          barriers.  */
-#undef DEF_SYNC_BUILTIN
-#define DEF_SYNC_BUILTIN(ENUM, NAME, TYPE, ATTRS) case ENUM:
-#include "sync-builtins.def"
-#undef DEF_SYNC_BUILTIN
-       case BUILT_IN_GOMP_ATOMIC_START:
-       case BUILT_IN_GOMP_ATOMIC_END:
-       case BUILT_IN_GOMP_BARRIER:
-       case BUILT_IN_GOMP_BARRIER_CANCEL:
-       case BUILT_IN_GOMP_TASKWAIT:
-       case BUILT_IN_GOMP_TASKGROUP_END:
-       case BUILT_IN_GOMP_CRITICAL_START:
-       case BUILT_IN_GOMP_CRITICAL_END:
-       case BUILT_IN_GOMP_CRITICAL_NAME_START:
-       case BUILT_IN_GOMP_CRITICAL_NAME_END:
-       case BUILT_IN_GOMP_LOOP_END:
-       case BUILT_IN_GOMP_LOOP_END_CANCEL:
-       case BUILT_IN_GOMP_ORDERED_START:
-       case BUILT_IN_GOMP_ORDERED_END:
-       case BUILT_IN_GOMP_SECTIONS_END:
-       case BUILT_IN_GOMP_SECTIONS_END_CANCEL:
-       case BUILT_IN_GOMP_SINGLE_COPY_START:
-       case BUILT_IN_GOMP_SINGLE_COPY_END:
-         return true;
-       default:
-         /* Fallthru to general call handling.  */;
-      }
+       }
+    }
 
   /* Check if base is a global static variable that is not written
      by the function.  */

Reply via email to