On Wed, 21 May 2014, Richard Biener wrote: > On Wed, 21 May 2014, Richard Biener wrote: > > > > > PR56955 prompted me to handle BUILT_IN_REALLOC just the same > > way we already handle BUILT_IN_STR[N]DUP. > > > > Bootstrap and regtest running on x86_64-unknown-linux-gnu. > > > > Now this will disambiguate *p and *q for p = realloc (q, n) > > for any value of n (including those that don't actually > > trigger re-allocation and thus where p == q after the call). > > I don't think that any such use would be valid - but I can > > certainly play safer here and implement the points-to part > > as a pass-through (that is, make p point to what q points). > > That's of course less optimization. > > Like with incremental > > Index: gcc/tree-ssa-structalias.c > =================================================================== > --- gcc/tree-ssa-structalias.c.orig 2014-05-21 15:37:58.762890034 > +0200 > +++ gcc/tree-ssa-structalias.c 2014-05-21 15:35:52.044898758 +0200 > @@ -4313,6 +4313,17 @@ find_func_aliases_for_builtin_call (stru > process_all_all_constraints (lhsc, rhsc); > lhsc.release (); > rhsc.release (); > + /* For realloc the resulting pointer can be equal to the > + argument as well. But only doing this wouldn't be > + correct because with ptr == 0 realloc behaves like malloc. > */ > + if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_REALLOC) > + { > + get_constraint_for (gimple_call_lhs (t), &lhsc); > + get_constraint_for (gimple_call_arg (t, 0), &rhsc); > + process_all_all_constraints (lhsc, rhsc); > + lhsc.release (); > + rhsc.release (); > + } > return true; > } > break; > > that of course makes it a somewhat pointless excercise if > points-to doesn't figure out sth fancy for the argument to > realloc (like its NULL or the result of an earlier malloc call, > still optimizes the testcase as expected).
The following is what I have applied after bootstrapping and testing on x86_64-unknown-linux-gnu. Richard. 2014-05-21 Richard Biener <rguent...@suse.de> * tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Handle BUILT_IN_REALLOC like BUILT_IN_STRDUP. (call_may_clobber_ref_p_1): Handle BUILT_IN_REALLOC as allocation and deallocation site. * tree-ssa-structalias.c (find_func_aliases_for_builtin_call): Handle BUILT_IN_REALLOC similar to BUILT_IN_STRDUP with also passing through the incoming points-to set. (handle_lhs_call): Use flags argument instead of recomputing it. (find_func_aliases_for_call): Call handle_lhs_call with proper call return flags. * gcc.dg/tree-ssa/alias-33.c: New testcase. Index: gcc/tree-ssa-alias.c =================================================================== *** gcc/tree-ssa-alias.c.orig 2014-05-21 16:21:18.995711011 +0200 --- gcc/tree-ssa-alias.c 2014-05-22 09:44:40.940400943 +0200 *************** ref_maybe_used_by_call_p_1 (gimple call, *** 1594,1599 **** --- 1594,1600 ---- /* 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; *************** call_may_clobber_ref_p_1 (gimple call, a *** 1991,1996 **** --- 1992,2006 ---- 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: Index: gcc/tree-ssa-structalias.c =================================================================== *** gcc/tree-ssa-structalias.c.orig 2014-05-21 16:21:18.995711011 +0200 --- gcc/tree-ssa-structalias.c 2014-05-22 09:43:05.807407492 +0200 *************** handle_lhs_call (gimple stmt, tree lhs, *** 3974,3980 **** /* If the call returns an argument unmodified override the rhs constraints. */ - flags = gimple_call_return_flags (stmt); if (flags & ERF_RETURNS_ARG && (flags & ERF_RETURN_ARG_MASK) < gimple_call_num_args (stmt)) { --- 3974,3979 ---- *************** find_func_aliases_for_builtin_call (stru *** 4299,4307 **** return true; case BUILT_IN_STRDUP: case BUILT_IN_STRNDUP: if (gimple_call_lhs (t)) { ! handle_lhs_call (t, gimple_call_lhs (t), gimple_call_flags (t), vNULL, fndecl); get_constraint_for_ptr_offset (gimple_call_lhs (t), NULL_TREE, &lhsc); --- 4298,4308 ---- return true; case BUILT_IN_STRDUP: case BUILT_IN_STRNDUP: + case BUILT_IN_REALLOC: if (gimple_call_lhs (t)) { ! handle_lhs_call (t, gimple_call_lhs (t), ! gimple_call_return_flags (t) | ERF_NOALIAS, vNULL, fndecl); get_constraint_for_ptr_offset (gimple_call_lhs (t), NULL_TREE, &lhsc); *************** find_func_aliases_for_builtin_call (stru *** 4312,4317 **** --- 4313,4329 ---- process_all_all_constraints (lhsc, rhsc); lhsc.release (); rhsc.release (); + /* For realloc the resulting pointer can be equal to the + argument as well. But only doing this wouldn't be + correct because with ptr == 0 realloc behaves like malloc. */ + if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_REALLOC) + { + get_constraint_for (gimple_call_lhs (t), &lhsc); + get_constraint_for (gimple_call_arg (t, 0), &rhsc); + process_all_all_constraints (lhsc, rhsc); + lhsc.release (); + rhsc.release (); + } return true; } break; *************** find_func_aliases_for_call (struct funct *** 4535,4541 **** else handle_rhs_call (t, &rhsc); if (gimple_call_lhs (t)) ! handle_lhs_call (t, gimple_call_lhs (t), flags, rhsc, fndecl); rhsc.release (); } else --- 4547,4554 ---- else handle_rhs_call (t, &rhsc); if (gimple_call_lhs (t)) ! handle_lhs_call (t, gimple_call_lhs (t), ! gimple_call_return_flags (t), rhsc, fndecl); rhsc.release (); } else Index: gcc/testsuite/gcc.dg/tree-ssa/alias-33.c =================================================================== *** /dev/null 1970-01-01 00:00:00.000000000 +0000 --- gcc/testsuite/gcc.dg/tree-ssa/alias-33.c 2014-05-22 09:43:05.808407492 +0200 *************** *** 0 **** --- 1,20 ---- + /* { dg-do run } */ + /* { dg-options "-O -fdump-tree-fre1-details" } */ + + int j; + int main () + { + int i = 1; + int **p; + j = 0; + p = __builtin_malloc (sizeof (int *)); + *p = &i; + p = __builtin_realloc (p, 2 * sizeof (int *)); + **p = 0; + if (i != 0) + __builtin_abort (); + return j; + } + + /* { dg-final { scan-tree-dump "Replaced j with 0" "fre1" } } */ + /* { dg-final { cleanup-tree-dump "fre1" } } */