Commit 779704e7 by Richard Guenther Committed by Richard Biener

tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle ADDR_EXPR pointers.

2009-06-19  Richard Guenther  <rguenther@suse.de>

	* tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle
	ADDR_EXPR pointers.
	(ptr_derefs_may_alias_p): Likewise.
	(ptr_deref_may_alias_ref_p_1): New function.
	(ptr_deref_may_alias_ref_p): Likewise.
	(ref_maybe_used_by_call_p_1): Handle builtins that are not
	covered by looking at the ESCAPED solution.
	(call_may_clobber_ref_p_1): Likewise.
	* tree-ssa-structalias.c (get_constraint_for_ptr_offset):
	Handle NULL_TREE offset.  Do not produce redundant constraints.
	(process_all_all_constraints): New helper function.
	(do_structure_copy): Use it.
	(handle_lhs_call): Likewise.
	(find_func_aliases): Handle some builtins with pointer arguments
	and/or return values explicitly.

	* gcc.c-torture/execute/20090618-1.c: New testcase.

From-SVN: r148718
parent 217655da
2009-06-19 Richard Guenther <rguenther@suse.de>
* tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Handle
ADDR_EXPR pointers.
(ptr_derefs_may_alias_p): Likewise.
(ptr_deref_may_alias_ref_p_1): New function.
(ptr_deref_may_alias_ref_p): Likewise.
(ref_maybe_used_by_call_p_1): Handle builtins that are not
covered by looking at the ESCAPED solution.
(call_may_clobber_ref_p_1): Likewise.
* tree-ssa-structalias.c (get_constraint_for_ptr_offset):
Handle NULL_TREE offset. Do not produce redundant constraints.
(process_all_all_constraints): New helper function.
(do_structure_copy): Use it.
(handle_lhs_call): Likewise.
(find_func_aliases): Handle some builtins with pointer arguments
and/or return values explicitly.
2009-06-19 Ian Lance Taylor <iant@google.com> 2009-06-19 Ian Lance Taylor <iant@google.com>
* varasm.c (const_rtx_hash_1): Remove const qualifier from shift. * varasm.c (const_rtx_hash_1): Remove const qualifier from shift.
......
2009-06-19 Richard Guenther <rguenther@suse.de>
* gcc.c-torture/execute/20090618-1.c: New testcase.
2009-06-19 Ian Lance Taylor <iant@google.com> 2009-06-19 Ian Lance Taylor <iant@google.com>
* gcc.dg/Wcxx-compat-17.c: New testcase. * gcc.dg/Wcxx-compat-17.c: New testcase.
......
extern void abort (void);
struct X { int *p; int *q; };
int foo(void)
{
int i = 0, j = 1;
struct X x, y;
int **p;
y.p = &i;
x.q = &j;
p = __builtin_mempcpy (&x, &y, sizeof (int *));
return **p;
}
int main()
{
if (foo() != 1)
abort ();
return 0;
}
...@@ -168,14 +168,9 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl) ...@@ -168,14 +168,9 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
{ {
struct ptr_info_def *pi; struct ptr_info_def *pi;
/* ??? During SCCVN/PRE we can end up with *&x during valueizing gcc_assert ((TREE_CODE (ptr) == SSA_NAME
operands. Likewise we can end up with dereferencing constant || TREE_CODE (ptr) == ADDR_EXPR
pointers. Just bail out in these cases for now. */ || TREE_CODE (ptr) == INTEGER_CST)
if (TREE_CODE (ptr) == ADDR_EXPR
|| TREE_CODE (ptr) == INTEGER_CST)
return true;
gcc_assert (TREE_CODE (ptr) == SSA_NAME
&& (TREE_CODE (decl) == VAR_DECL && (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == PARM_DECL || TREE_CODE (decl) == PARM_DECL
|| TREE_CODE (decl) == RESULT_DECL)); || TREE_CODE (decl) == RESULT_DECL));
...@@ -184,6 +179,29 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl) ...@@ -184,6 +179,29 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
if (!may_be_aliased (decl)) if (!may_be_aliased (decl))
return false; return false;
/* ADDR_EXPR pointers either just offset another pointer or directly
specify the pointed-to set. */
if (TREE_CODE (ptr) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (ptr, 0));
if (base
&& INDIRECT_REF_P (base))
ptr = TREE_OPERAND (base, 0);
else if (base
&& SSA_VAR_P (base))
return operand_equal_p (base, decl, 0);
else if (base
&& CONSTANT_CLASS_P (base))
return false;
else
return true;
}
/* We can end up with dereferencing constant pointers.
Just bail out in this case. */
if (TREE_CODE (ptr) == INTEGER_CST)
return true;
/* If we do not have useful points-to information for this pointer /* If we do not have useful points-to information for this pointer
we cannot disambiguate anything else. */ we cannot disambiguate anything else. */
pi = SSA_NAME_PTR_INFO (ptr); pi = SSA_NAME_PTR_INFO (ptr);
...@@ -202,18 +220,46 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2) ...@@ -202,18 +220,46 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
{ {
struct ptr_info_def *pi1, *pi2; struct ptr_info_def *pi1, *pi2;
/* ??? During SCCVN/PRE we can end up with *&x during valueizing gcc_assert ((TREE_CODE (ptr1) == SSA_NAME
operands. Likewise we can end up with dereferencing constant || TREE_CODE (ptr1) == ADDR_EXPR
pointers. Just bail out in these cases for now. */ || TREE_CODE (ptr1) == INTEGER_CST)
if (TREE_CODE (ptr1) == ADDR_EXPR && (TREE_CODE (ptr2) == SSA_NAME
|| TREE_CODE (ptr1) == INTEGER_CST || TREE_CODE (ptr2) == ADDR_EXPR
|| TREE_CODE (ptr2) == ADDR_EXPR || TREE_CODE (ptr2) == INTEGER_CST));
/* ADDR_EXPR pointers either just offset another pointer or directly
specify the pointed-to set. */
if (TREE_CODE (ptr1) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (ptr1, 0));
if (base
&& INDIRECT_REF_P (base))
ptr1 = TREE_OPERAND (base, 0);
else if (base
&& SSA_VAR_P (base))
return ptr_deref_may_alias_decl_p (ptr2, base);
else
return true;
}
if (TREE_CODE (ptr2) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (ptr2, 0));
if (base
&& INDIRECT_REF_P (base))
ptr2 = TREE_OPERAND (base, 0);
else if (base
&& SSA_VAR_P (base))
return ptr_deref_may_alias_decl_p (ptr1, base);
else
return true;
}
/* We can end up with dereferencing constant pointers.
Just bail out in this case. */
if (TREE_CODE (ptr1) == INTEGER_CST
|| TREE_CODE (ptr2) == INTEGER_CST) || TREE_CODE (ptr2) == INTEGER_CST)
return true; return true;
gcc_assert (TREE_CODE (ptr1) == SSA_NAME
&& TREE_CODE (ptr2) == SSA_NAME);
/* We may end up with two empty points-to solutions for two same pointers. /* We may end up with two empty points-to solutions for two same pointers.
In this case we still want to say both pointers alias, so shortcut In this case we still want to say both pointers alias, so shortcut
that here. */ that here. */
...@@ -232,6 +278,31 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2) ...@@ -232,6 +278,31 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
return pt_solutions_intersect (&pi1->pt, &pi2->pt); return pt_solutions_intersect (&pi1->pt, &pi2->pt);
} }
/* Return true if dereferencing PTR may alias *REF.
The caller is responsible for applying TBAA to see if PTR
may access *REF at all. */
static bool
ptr_deref_may_alias_ref_p_1 (tree ptr, ao_ref *ref)
{
tree base = ao_ref_base (ref);
if (INDIRECT_REF_P (base))
return ptr_derefs_may_alias_p (ptr, TREE_OPERAND (base, 0));
else if (SSA_VAR_P (base))
return ptr_deref_may_alias_decl_p (ptr, base);
return true;
}
static bool
ptr_deref_may_alias_ref_p (tree ptr, tree ref)
{
ao_ref r;
ao_ref_init (&r, ref);
return ptr_deref_may_alias_ref_p_1 (ptr, &r);
}
/* Dump alias information on FILE. */ /* Dump alias information on FILE. */
...@@ -778,7 +849,7 @@ refs_output_dependent_p (tree store1, tree store2) ...@@ -778,7 +849,7 @@ refs_output_dependent_p (tree store1, tree store2)
static bool static bool
ref_maybe_used_by_call_p_1 (gimple call, tree ref) ref_maybe_used_by_call_p_1 (gimple call, tree ref)
{ {
tree base; tree base, callee;
unsigned i; unsigned i;
int flags = gimple_call_flags (call); int flags = gimple_call_flags (call);
...@@ -803,13 +874,41 @@ ref_maybe_used_by_call_p_1 (gimple call, tree ref) ...@@ -803,13 +874,41 @@ ref_maybe_used_by_call_p_1 (gimple call, tree ref)
&& !is_global_var (base)) && !is_global_var (base))
goto process_args; goto process_args;
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_BCOPY:
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:
{
tree src = gimple_call_arg (call, 1);
return ptr_deref_may_alias_ref_p (src, ref);
}
default:
/* Fallthru to general call handling. */;
}
/* Check if base is a global static variable that is not read /* Check if base is a global static variable that is not read
by the function. */ by the function. */
if (TREE_CODE (base) == VAR_DECL if (TREE_CODE (base) == VAR_DECL
&& TREE_STATIC (base) && TREE_STATIC (base)
&& !TREE_PUBLIC (base)) && !TREE_PUBLIC (base))
{ {
tree callee = gimple_call_fndecl (call);
bitmap not_read; bitmap not_read;
if (callee != NULL_TREE if (callee != NULL_TREE
...@@ -901,6 +1000,7 @@ static bool ...@@ -901,6 +1000,7 @@ static bool
call_may_clobber_ref_p_1 (gimple call, ao_ref *ref) call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
{ {
tree base; tree base;
tree callee;
/* If the call is pure or const it cannot clobber anything. */ /* If the call is pure or const it cannot clobber anything. */
if (gimple_call_flags (call) if (gimple_call_flags (call)
...@@ -926,18 +1026,87 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref) ...@@ -926,18 +1026,87 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
|| !is_global_var (base))) || !is_global_var (base)))
return false; return false;
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_BCOPY:
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:
{
tree dest = gimple_call_arg (call, 0);
return ptr_deref_may_alias_ref_p_1 (dest, 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. Same is true for memset. */
case BUILT_IN_FREE:
case BUILT_IN_MEMSET:
{
tree ptr = gimple_call_arg (call, 0);
return ptr_deref_may_alias_ref_p_1 (ptr, ref);
}
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:
{
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);
return ptr_deref_may_alias_ref_p_1 (out, ref);
}
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));
}
default:
/* Fallthru to general call handling. */;
}
/* Check if base is a global static variable that is not written /* Check if base is a global static variable that is not written
by the function. */ by the function. */
if (TREE_CODE (base) == VAR_DECL if (callee != NULL_TREE
&& TREE_CODE (base) == VAR_DECL
&& TREE_STATIC (base) && TREE_STATIC (base)
&& !TREE_PUBLIC (base)) && !TREE_PUBLIC (base))
{ {
tree callee = gimple_call_fndecl (call);
bitmap not_written; bitmap not_written;
if (callee != NULL_TREE if ((not_written
&& (not_written = ipa_reference_get_not_written_global (cgraph_node (callee)))
= ipa_reference_get_not_written_global (cgraph_node (callee)))
&& bitmap_bit_p (not_written, DECL_UID (base))) && bitmap_bit_p (not_written, DECL_UID (base)))
return false; return false;
} }
......
...@@ -2857,7 +2857,8 @@ get_constraint_for_ptr_offset (tree ptr, tree offset, ...@@ -2857,7 +2857,8 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
in a HOST_WIDE_INT, we have to fall back to a conservative in a HOST_WIDE_INT, we have to fall back to a conservative
solution which includes all sub-fields of all pointed-to solution which includes all sub-fields of all pointed-to
variables of ptr. */ variables of ptr. */
if (!host_integerp (offset, 0)) if (offset == NULL_TREE
|| !host_integerp (offset, 0))
rhsoffset = UNKNOWN_OFFSET; rhsoffset = UNKNOWN_OFFSET;
else else
{ {
...@@ -2896,7 +2897,8 @@ get_constraint_for_ptr_offset (tree ptr, tree offset, ...@@ -2896,7 +2897,8 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
c2.var = temp->id; c2.var = temp->id;
c2.type = ADDRESSOF; c2.type = ADDRESSOF;
c2.offset = 0; c2.offset = 0;
VEC_safe_push (ce_s, heap, *results, &c2); if (c2.var != c->var)
VEC_safe_push (ce_s, heap, *results, &c2);
temp = temp->next; temp = temp->next;
} }
while (temp); while (temp);
...@@ -3239,6 +3241,37 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results) ...@@ -3239,6 +3241,37 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results)
get_constraint_for_1 (t, results, false); get_constraint_for_1 (t, results, false);
} }
/* Efficiently generates constraints from all entries in *RHSC to all
entries in *LHSC. */
static void
process_all_all_constraints (VEC (ce_s, heap) *lhsc, VEC (ce_s, heap) *rhsc)
{
struct constraint_expr *lhsp, *rhsp;
unsigned i, j;
if (VEC_length (ce_s, lhsc) <= 1
|| VEC_length (ce_s, rhsc) <= 1)
{
for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i)
for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); ++j)
process_constraint (new_constraint (*lhsp, *rhsp));
}
else
{
struct constraint_expr tmp;
tree tmpvar = create_tmp_var_raw (ptr_type_node, "allallcopytmp");
tmp.var = get_vi_for_tree (tmpvar)->id;
tmp.type = SCALAR;
tmp.offset = 0;
for (i = 0; VEC_iterate (ce_s, rhsc, i, rhsp); ++i)
process_constraint (new_constraint (tmp, *rhsp));
for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i)
process_constraint (new_constraint (*lhsp, tmp));
}
}
/* Handle aggregate copies by expanding into copies of the respective /* Handle aggregate copies by expanding into copies of the respective
fields of the structures. */ fields of the structures. */
...@@ -3256,18 +3289,7 @@ do_structure_copy (tree lhsop, tree rhsop) ...@@ -3256,18 +3289,7 @@ do_structure_copy (tree lhsop, tree rhsop)
if (lhsp->type == DEREF if (lhsp->type == DEREF
|| (lhsp->type == ADDRESSOF && lhsp->var == anything_id) || (lhsp->type == ADDRESSOF && lhsp->var == anything_id)
|| rhsp->type == DEREF) || rhsp->type == DEREF)
{ process_all_all_constraints (lhsc, rhsc);
struct constraint_expr tmp;
tree tmpvar = create_tmp_var_raw (ptr_type_node,
"structcopydereftmp");
tmp.var = get_vi_for_tree (tmpvar)->id;
tmp.type = SCALAR;
tmp.offset = 0;
for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); ++j)
process_constraint (new_constraint (tmp, *rhsp));
for (j = 0; VEC_iterate (ce_s, lhsc, j, lhsp); ++j)
process_constraint (new_constraint (*lhsp, tmp));
}
else if (lhsp->type == SCALAR else if (lhsp->type == SCALAR
&& (rhsp->type == SCALAR && (rhsp->type == SCALAR
|| rhsp->type == ADDRESSOF)) || rhsp->type == ADDRESSOF))
...@@ -3426,8 +3448,6 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc) ...@@ -3426,8 +3448,6 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
} }
else if (VEC_length (ce_s, rhsc) > 0) else if (VEC_length (ce_s, rhsc) > 0)
{ {
struct constraint_expr *lhsp, *rhsp;
unsigned int i, j;
/* If the store is to a global decl make sure to /* If the store is to a global decl make sure to
add proper escape constraints. */ add proper escape constraints. */
lhs = get_base_address (lhs); lhs = get_base_address (lhs);
...@@ -3441,9 +3461,7 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc) ...@@ -3441,9 +3461,7 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
tmpc.type = SCALAR; tmpc.type = SCALAR;
VEC_safe_push (ce_s, heap, lhsc, &tmpc); VEC_safe_push (ce_s, heap, lhsc, &tmpc);
} }
for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i) process_all_all_constraints (lhsc, rhsc);
for (j = 0; VEC_iterate (ce_s, rhsc, j, rhsp); ++j)
process_constraint (new_constraint (*lhsp, *rhsp));
} }
VEC_free (ce_s, heap, lhsc); VEC_free (ce_s, heap, lhsc);
} }
...@@ -3608,6 +3626,108 @@ find_func_aliases (gimple origt) ...@@ -3608,6 +3626,108 @@ find_func_aliases (gimple origt)
pointer passed by address. */ pointer passed by address. */
else if (is_gimple_call (t)) else if (is_gimple_call (t))
{ {
tree fndecl;
if ((fndecl = gimple_call_fndecl (t)) != NULL_TREE
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
/* ??? All builtins that are handled here need to be handled
in the alias-oracle query functions explicitly! */
switch (DECL_FUNCTION_CODE (fndecl))
{
/* All the following functions return a pointer to the same object
as their first argument points to. The functions do not add
to the ESCAPED solution. The functions make the first argument
pointed to memory point to what the second argument pointed to
memory points to. */
case BUILT_IN_STRCPY:
case BUILT_IN_STRNCPY:
case BUILT_IN_BCOPY:
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:
{
tree res = gimple_call_lhs (t);
tree dest = gimple_call_arg (t, 0);
tree src = gimple_call_arg (t, 1);
if (res != NULL_TREE)
{
get_constraint_for (res, &lhsc);
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMPCPY
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPCPY
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_STPNCPY)
get_constraint_for_ptr_offset (dest, NULL_TREE, &rhsc);
else
get_constraint_for (dest, &rhsc);
process_all_all_constraints (lhsc, rhsc);
VEC_free (ce_s, heap, lhsc);
VEC_free (ce_s, heap, rhsc);
}
get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc);
do_deref (&lhsc);
do_deref (&rhsc);
process_all_all_constraints (lhsc, rhsc);
VEC_free (ce_s, heap, lhsc);
VEC_free (ce_s, heap, rhsc);
return;
}
case BUILT_IN_MEMSET:
{
tree res = gimple_call_lhs (t);
tree dest = gimple_call_arg (t, 0);
unsigned i;
ce_s *lhsp;
struct constraint_expr ac;
if (res != NULL_TREE)
{
get_constraint_for (res, &lhsc);
get_constraint_for (dest, &rhsc);
process_all_all_constraints (lhsc, rhsc);
VEC_free (ce_s, heap, lhsc);
VEC_free (ce_s, heap, rhsc);
}
get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
do_deref (&lhsc);
ac.type = SCALAR;
ac.var = integer_id;
ac.offset = 0;
for (i = 0; VEC_iterate (ce_s, lhsc, i, lhsp); ++i)
process_constraint (new_constraint (*lhsp, ac));
VEC_free (ce_s, heap, lhsc);
return;
}
/* All the following functions do not return pointers, do not
modify the points-to sets of memory reachable from their
arguments and do not add to the ESCAPED solution. */
case BUILT_IN_SINCOS:
case BUILT_IN_SINCOSF:
case BUILT_IN_SINCOSL:
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_FREE:
return;
/* printf-style functions may have hooks to set pointers to
point to somewhere into the generated string. Leave them
for a later excercise... */
default:
/* Fallthru to general call handling. */;
}
if (!in_ipa_mode) if (!in_ipa_mode)
{ {
VEC(ce_s, heap) *rhsc = NULL; VEC(ce_s, heap) *rhsc = NULL;
...@@ -3724,7 +3844,6 @@ find_func_aliases (gimple origt) ...@@ -3724,7 +3844,6 @@ find_func_aliases (gimple origt)
do_structure_copy (lhsop, rhsop); do_structure_copy (lhsop, rhsop);
else else
{ {
unsigned int j;
struct constraint_expr temp; struct constraint_expr temp;
get_constraint_for (lhsop, &lhsc); get_constraint_for (lhsop, &lhsc);
...@@ -3743,14 +3862,7 @@ find_func_aliases (gimple origt) ...@@ -3743,14 +3862,7 @@ find_func_aliases (gimple origt)
temp.offset = 0; temp.offset = 0;
VEC_safe_push (ce_s, heap, rhsc, &temp); VEC_safe_push (ce_s, heap, rhsc, &temp);
} }
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++) process_all_all_constraints (lhsc, rhsc);
{
struct constraint_expr *c2;
unsigned int k;
for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++)
process_constraint (new_constraint (*c, *c2));
}
} }
/* If there is a store to a global variable the rhs escapes. */ /* If there is a store to a global variable the rhs escapes. */
if ((lhsop = get_base_address (lhsop)) != NULL_TREE if ((lhsop = get_base_address (lhsop)) != NULL_TREE
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment