+ callee = gimple_call_fndecl (call);
+
+ /* 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. */
+ if (callee != NULL_TREE
+ && DECL_BUILT_IN_CLASS (callee) == 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_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_ALLOCA_WITH_ALIGN:
+ case BUILT_IN_ASSUME_ALIGNED:
+ return false;
+ /* 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);
+ }
+ 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_TASKWAIT:
+ 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_ORDERED_START:
+ case BUILT_IN_GOMP_ORDERED_END:
+ case BUILT_IN_GOMP_PARALLEL_END:
+ case BUILT_IN_GOMP_SECTIONS_END:
+ case BUILT_IN_GOMP_SINGLE_COPY_START:
+ case BUILT_IN_GOMP_SINGLE_COPY_END:
+ return true;
+ default:
+ /* Fallthru to general call handling. */;
+ }
+