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
This commit is contained in:
parent
217655da6f
commit
779704e7cf
@ -1,3 +1,21 @@
|
||||
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>
|
||||
|
||||
* varasm.c (const_rtx_hash_1): Remove const qualifier from shift.
|
||||
|
@ -1,3 +1,7 @@
|
||||
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>
|
||||
|
||||
* gcc.dg/Wcxx-compat-17.c: New testcase.
|
||||
|
21
gcc/testsuite/gcc.c-torture/execute/20090618-1.c
Normal file
21
gcc/testsuite/gcc.c-torture/execute/20090618-1.c
Normal file
@ -0,0 +1,21 @@
|
||||
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)
|
||||
{
|
||||
struct ptr_info_def *pi;
|
||||
|
||||
/* ??? During SCCVN/PRE we can end up with *&x during valueizing
|
||||
operands. Likewise we can end up with dereferencing constant
|
||||
pointers. Just bail out in these cases for now. */
|
||||
if (TREE_CODE (ptr) == ADDR_EXPR
|
||||
|| TREE_CODE (ptr) == INTEGER_CST)
|
||||
return true;
|
||||
|
||||
gcc_assert (TREE_CODE (ptr) == SSA_NAME
|
||||
gcc_assert ((TREE_CODE (ptr) == SSA_NAME
|
||||
|| TREE_CODE (ptr) == ADDR_EXPR
|
||||
|| TREE_CODE (ptr) == INTEGER_CST)
|
||||
&& (TREE_CODE (decl) == VAR_DECL
|
||||
|| TREE_CODE (decl) == PARM_DECL
|
||||
|| TREE_CODE (decl) == RESULT_DECL));
|
||||
@ -184,6 +179,29 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
|
||||
if (!may_be_aliased (decl))
|
||||
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
|
||||
we cannot disambiguate anything else. */
|
||||
pi = SSA_NAME_PTR_INFO (ptr);
|
||||
@ -202,18 +220,46 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
|
||||
{
|
||||
struct ptr_info_def *pi1, *pi2;
|
||||
|
||||
/* ??? During SCCVN/PRE we can end up with *&x during valueizing
|
||||
operands. Likewise we can end up with dereferencing constant
|
||||
pointers. Just bail out in these cases for now. */
|
||||
if (TREE_CODE (ptr1) == ADDR_EXPR
|
||||
|| TREE_CODE (ptr1) == INTEGER_CST
|
||||
|| TREE_CODE (ptr2) == ADDR_EXPR
|
||||
gcc_assert ((TREE_CODE (ptr1) == SSA_NAME
|
||||
|| TREE_CODE (ptr1) == ADDR_EXPR
|
||||
|| TREE_CODE (ptr1) == INTEGER_CST)
|
||||
&& (TREE_CODE (ptr2) == SSA_NAME
|
||||
|| 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)
|
||||
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.
|
||||
In this case we still want to say both pointers alias, so shortcut
|
||||
that here. */
|
||||
@ -232,6 +278,31 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
|
||||
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. */
|
||||
|
||||
@ -778,7 +849,7 @@ refs_output_dependent_p (tree store1, tree store2)
|
||||
static bool
|
||||
ref_maybe_used_by_call_p_1 (gimple call, tree ref)
|
||||
{
|
||||
tree base;
|
||||
tree base, callee;
|
||||
unsigned i;
|
||||
int flags = gimple_call_flags (call);
|
||||
|
||||
@ -803,13 +874,41 @@ ref_maybe_used_by_call_p_1 (gimple call, tree ref)
|
||||
&& !is_global_var (base))
|
||||
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
|
||||
by the function. */
|
||||
if (TREE_CODE (base) == VAR_DECL
|
||||
&& TREE_STATIC (base)
|
||||
&& !TREE_PUBLIC (base))
|
||||
{
|
||||
tree callee = gimple_call_fndecl (call);
|
||||
bitmap not_read;
|
||||
|
||||
if (callee != NULL_TREE
|
||||
@ -901,6 +1000,7 @@ static bool
|
||||
call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
|
||||
{
|
||||
tree base;
|
||||
tree callee;
|
||||
|
||||
/* If the call is pure or const it cannot clobber anything. */
|
||||
if (gimple_call_flags (call)
|
||||
@ -926,18 +1026,87 @@ call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
|
||||
|| !is_global_var (base)))
|
||||
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
|
||||
by the function. */
|
||||
if (TREE_CODE (base) == VAR_DECL
|
||||
if (callee != NULL_TREE
|
||||
&& TREE_CODE (base) == VAR_DECL
|
||||
&& TREE_STATIC (base)
|
||||
&& !TREE_PUBLIC (base))
|
||||
{
|
||||
tree callee = gimple_call_fndecl (call);
|
||||
bitmap not_written;
|
||||
|
||||
if (callee != NULL_TREE
|
||||
&& (not_written
|
||||
= ipa_reference_get_not_written_global (cgraph_node (callee)))
|
||||
if ((not_written
|
||||
= ipa_reference_get_not_written_global (cgraph_node (callee)))
|
||||
&& bitmap_bit_p (not_written, DECL_UID (base)))
|
||||
return false;
|
||||
}
|
||||
|
@ -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
|
||||
solution which includes all sub-fields of all pointed-to
|
||||
variables of ptr. */
|
||||
if (!host_integerp (offset, 0))
|
||||
if (offset == NULL_TREE
|
||||
|| !host_integerp (offset, 0))
|
||||
rhsoffset = UNKNOWN_OFFSET;
|
||||
else
|
||||
{
|
||||
@ -2896,7 +2897,8 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
|
||||
c2.var = temp->id;
|
||||
c2.type = ADDRESSOF;
|
||||
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;
|
||||
}
|
||||
while (temp);
|
||||
@ -3239,6 +3241,37 @@ get_constraint_for (tree t, VEC (ce_s, heap) **results)
|
||||
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
|
||||
fields of the structures. */
|
||||
|
||||
@ -3256,18 +3289,7 @@ do_structure_copy (tree lhsop, tree rhsop)
|
||||
if (lhsp->type == DEREF
|
||||
|| (lhsp->type == ADDRESSOF && lhsp->var == anything_id)
|
||||
|| rhsp->type == DEREF)
|
||||
{
|
||||
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));
|
||||
}
|
||||
process_all_all_constraints (lhsc, rhsc);
|
||||
else if (lhsp->type == SCALAR
|
||||
&& (rhsp->type == SCALAR
|
||||
|| rhsp->type == ADDRESSOF))
|
||||
@ -3426,8 +3448,6 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
|
||||
}
|
||||
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
|
||||
add proper escape constraints. */
|
||||
lhs = get_base_address (lhs);
|
||||
@ -3441,9 +3461,7 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
|
||||
tmpc.type = SCALAR;
|
||||
VEC_safe_push (ce_s, heap, lhsc, &tmpc);
|
||||
}
|
||||
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));
|
||||
process_all_all_constraints (lhsc, rhsc);
|
||||
}
|
||||
VEC_free (ce_s, heap, lhsc);
|
||||
}
|
||||
@ -3608,6 +3626,108 @@ find_func_aliases (gimple origt)
|
||||
pointer passed by address. */
|
||||
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)
|
||||
{
|
||||
VEC(ce_s, heap) *rhsc = NULL;
|
||||
@ -3724,7 +3844,6 @@ find_func_aliases (gimple origt)
|
||||
do_structure_copy (lhsop, rhsop);
|
||||
else
|
||||
{
|
||||
unsigned int j;
|
||||
struct constraint_expr temp;
|
||||
get_constraint_for (lhsop, &lhsc);
|
||||
|
||||
@ -3743,14 +3862,7 @@ find_func_aliases (gimple origt)
|
||||
temp.offset = 0;
|
||||
VEC_safe_push (ce_s, heap, rhsc, &temp);
|
||||
}
|
||||
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
|
||||
{
|
||||
struct constraint_expr *c2;
|
||||
unsigned int k;
|
||||
|
||||
for (k = 0; VEC_iterate (ce_s, rhsc, k, c2); k++)
|
||||
process_constraint (new_constraint (*c, *c2));
|
||||
}
|
||||
process_all_all_constraints (lhsc, rhsc);
|
||||
}
|
||||
/* If there is a store to a global variable the rhs escapes. */
|
||||
if ((lhsop = get_base_address (lhsop)) != NULL_TREE
|
||||
|
Loading…
Reference in New Issue
Block a user