[PATCH] Fix pointer-arithmetic in PTA (revised)
Richard Guenther
rguenther@suse.de
Mon Jul 7 14:13:00 GMT 2008
This is the revised version according to discussion with Danny. It
makes sure to not break ipa-pta by adding a new flag to varinfos
that says if the field is representing a full variable (the function
decl var does not, but its parameters and the result do).
We can use this flag to distinguish between globbing behavior and
usual arithmetic behavior. I have added more testcases, including
some ipa-pta testcases that make sure the points-to results are
correct.
Bootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk?
Thanks,
Richard.
2008-07-04 Richard Guenther <rguenther@suse.de>
* tree-ssa-structalias.c (struct variable_info): Add is_full_var flag.
(new_var_info): Set it to false.
(solution_set_add): Correctly handle pointers outside a var and
inside a field.
(type_safe): Treat variables with is_full_var properly.
(do_sd_constraint): Likewise.
(do_ds_constraint): Likewise.
(process_constraint): Remove zeroing offset for !use_field_sensitive.
(get_constraint_for_ptr_offset): New function.
(get_constraint_for_component_ref): For addresses at least include
the last field of the variable. Handle is_full_vars properly.
(get_constraint_for_1): Factor common code, handle POINTER_PLUS_EXPR.
(handle_ptr_arith): Remove.
(find_func_aliases): Simplify assignment handling.
(create_function_info_for): For parameter and result varinfos set
is_full_var flag.
(create_variable_info_for): Set is_full_var flag whenever we
just created a single varinfo for a decl.
(init_alias_vars): Initialize use_field_sensitive from
max-fields-for-field-sensitive parameter.
* gcc.dg/torture/pta-ptrarith-1.c: New testcase.
* gcc.dg/torture/pta-ptrarith-2.c: Likewise.
* gcc.dg/torture/ipa-pta-1.c: Likewise.
Index: trunk/gcc/tree-ssa-structalias.c
===================================================================
*** trunk.orig/gcc/tree-ssa-structalias.c 2008-07-07 13:48:19.000000000 +0200
--- trunk/gcc/tree-ssa-structalias.c 2008-07-07 14:10:32.000000000 +0200
*************** struct variable_info
*** 220,225 ****
--- 220,228 ----
/* True for variables whose size is not known or variable. */
unsigned int is_unknown_size_var:1;
+ /* True for (sub-)fields that represent a whole variable. */
+ unsigned int is_full_var : 1;
+
/* True if this is a heap variable. */
unsigned int is_heap_var:1;
*************** new_var_info (tree t, unsigned int id, c
*** 373,378 ****
--- 376,382 ----
ret->is_heap_var = false;
ret->is_special_var = false;
ret->is_unknown_size_var = false;
+ ret->is_full_var = false;
var = t;
if (TREE_CODE (var) == SSA_NAME)
var = SSA_NAME_VAR (var);
*************** solution_set_add (bitmap set, unsigned H
*** 752,773 ****
EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
{
! /* If this is a properly sized variable, only add offset if it's
! less than end. Otherwise, it is globbed to a single
! variable. */
! if ((get_varinfo (i)->offset + offset) < get_varinfo (i)->fullsize)
{
! unsigned HOST_WIDE_INT fieldoffset = get_varinfo (i)->offset + offset;
! varinfo_t v = first_vi_for_offset (get_varinfo (i), fieldoffset);
if (!v)
! continue;
bitmap_set_bit (result, v->id);
! }
! else if (get_varinfo (i)->is_artificial_var
! || get_varinfo (i)->is_unknown_size_var)
! {
! bitmap_set_bit (result, i);
}
}
--- 756,787 ----
EXECUTE_IF_SET_IN_BITMAP (set, 0, i, bi)
{
! varinfo_t vi = get_varinfo (i);
! /* If this is a variable with just one field just set its bit
! in the result. */
! if (vi->is_artificial_var
! || vi->is_unknown_size_var
! || vi->is_full_var)
! bitmap_set_bit (result, i);
! else
{
! unsigned HOST_WIDE_INT fieldoffset = vi->offset + offset;
! varinfo_t v = first_vi_for_offset (vi, fieldoffset);
! /* If the result is outside of the variable use the last field. */
if (!v)
! {
! v = vi;
! while (v->next != NULL)
! v = v->next;
! }
bitmap_set_bit (result, v->id);
! /* If the result is not exactly at fieldoffset include the next
! field as well. See get_constraint_for_ptr_offset for more
! rationale. */
! if (v->offset != fieldoffset
! && v->next != NULL)
! bitmap_set_bit (result, v->next->id);
}
}
*************** type_safe (unsigned int n, unsigned HOST
*** 1375,1381 ****
0. */
if (ninfo->is_special_var
|| ninfo->is_artificial_var
! || ninfo->is_unknown_size_var)
{
*offset = 0;
return true;
--- 1389,1396 ----
0. */
if (ninfo->is_special_var
|| ninfo->is_artificial_var
! || ninfo->is_unknown_size_var
! || ninfo->is_full_var)
{
*offset = 0;
return true;
*************** do_sd_constraint (constraint_graph_t gra
*** 1415,1421 ****
sub-fields off. This avoids quadratic behavior. */
EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
{
! varinfo_t v = lookup_vi_for_tree (get_varinfo (j)->decl);
if (v->next != NULL)
{
if (vars == NULL)
--- 1430,1440 ----
sub-fields off. This avoids quadratic behavior. */
EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
{
! varinfo_t v = get_varinfo (j);
! if (v->is_full_var)
! continue;
!
! v = lookup_vi_for_tree (v->decl);
if (v->next != NULL)
{
if (vars == NULL)
*************** do_sd_constraint (constraint_graph_t gra
*** 1455,1460 ****
--- 1474,1480 ----
unsigned int t;
v = first_vi_for_offset (get_varinfo (j), fieldoffset);
+ /* If the access is outside of the variable we can ignore it. */
if (!v)
continue;
t = find (v->id);
*************** do_ds_constraint (constraint_t c, bitmap
*** 1507,1515 ****
unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
varinfo_t v;
! v = first_vi_for_offset (get_varinfo (j), fieldoffset);
! if (!v)
! continue;
t = find (v->id);
if (bitmap_set_bit (get_varinfo (t)->solution, anything_id)
--- 1527,1540 ----
unsigned HOST_WIDE_INT fieldoffset = jvi->offset + loff;
varinfo_t v;
! v = get_varinfo (j);
! if (!v->is_full_var)
! {
! v = first_vi_for_offset (v, fieldoffset);
! /* If the access is outside of the variable we can ignore it. */
! if (!v)
! continue;
! }
t = find (v->id);
if (bitmap_set_bit (get_varinfo (t)->solution, anything_id)
*************** do_ds_constraint (constraint_t c, bitmap
*** 1535,1540 ****
--- 1560,1566 ----
bitmap tmp;
v = first_vi_for_offset (get_varinfo (j), fieldoffset);
+ /* If the access is outside of the variable we can ignore it. */
if (!v)
continue;
t = find (v->id);
*************** process_constraint (constraint_t t)
*** 2597,2608 ****
gcc_assert (rhs.var < VEC_length (varinfo_t, varmap));
gcc_assert (lhs.var < VEC_length (varinfo_t, varmap));
- if (!use_field_sensitive)
- {
- t->rhs.offset = 0;
- t->lhs.offset = 0;
- }
-
/* ANYTHING == ANYTHING is pointless. */
if (lhs.var == anything_id && rhs.var == anything_id)
return;
--- 2623,2628 ----
*************** bitpos_of_field (const tree fdecl)
*** 2678,2683 ****
--- 2698,2816 ----
}
+ /* Get constraint expressions for offsetting PTR by OFFSET. Stores the
+ resulting constraint expressions in *RESULTS. */
+
+ static void
+ get_constraint_for_ptr_offset (tree ptr, tree offset,
+ VEC (ce_s, heap) **results)
+ {
+ struct constraint_expr *c;
+ unsigned int j, n;
+ unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
+
+ /* If we do not do field-sensitive PTA adding offsets to pointers
+ does not change the points-to solution. */
+ if (!use_field_sensitive)
+ {
+ get_constraint_for (ptr, results);
+ return;
+ }
+
+ /* If the offset is not a non-negative integer constant that fits
+ 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.
+ ??? As we do not have the ability to express this, fall back
+ to anything. */
+ if (!host_integerp (offset, 1))
+ {
+ struct constraint_expr temp;
+ temp.var = anything_id;
+ temp.type = SCALAR;
+ temp.offset = 0;
+ VEC_safe_push (ce_s, heap, *results, &temp);
+ return;
+ }
+
+ /* Make sure the bit-offset also fits. */
+ rhsunitoffset = TREE_INT_CST_LOW (offset);
+ rhsoffset = rhsunitoffset * BITS_PER_UNIT;
+ if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
+ {
+ struct constraint_expr temp;
+ temp.var = anything_id;
+ temp.type = SCALAR;
+ temp.offset = 0;
+ VEC_safe_push (ce_s, heap, *results, &temp);
+ return;
+ }
+
+ get_constraint_for (ptr, results);
+ if (rhsoffset == 0)
+ return;
+
+ /* As we are eventually appending to the solution do not use
+ VEC_iterate here. */
+ n = VEC_length (ce_s, *results);
+ for (j = 0; j < n; j++)
+ {
+ varinfo_t curr;
+ c = VEC_index (ce_s, *results, j);
+ curr = get_varinfo (c->var);
+
+ if (c->type == ADDRESSOF
+ && !curr->is_full_var)
+ {
+ varinfo_t temp, curr = get_varinfo (c->var);
+
+ /* Search the sub-field which overlaps with the
+ pointed-to offset. As we deal with positive offsets
+ only, we can start the search from the current variable. */
+ temp = first_vi_for_offset (curr, curr->offset + rhsoffset);
+
+ /* If the result is outside of the variable we have to provide
+ a conservative result, as the variable is still reachable
+ from the resulting pointer (even though it technically
+ cannot point to anything). The last sub-field is such
+ a conservative result.
+ ??? If we always had a sub-field for &object + 1 then
+ we could represent this in a more precise way. */
+ if (temp == NULL)
+ {
+ temp = curr;
+ while (temp->next != NULL)
+ temp = temp->next;
+ continue;
+ }
+
+ /* If the found variable is not exactly at the pointed to
+ result, we have to include the next variable in the
+ solution as well. Otherwise two increments by offset / 2
+ do not result in the same or a conservative superset
+ solution. */
+ if (temp->offset != curr->offset + rhsoffset
+ && temp->next != NULL)
+ {
+ struct constraint_expr c2;
+ c2.var = temp->next->id;
+ c2.type = ADDRESSOF;
+ c2.offset = 0;
+ VEC_safe_push (ce_s, heap, *results, &c2);
+ }
+ c->var = temp->id;
+ c->offset = 0;
+ }
+ else if (c->type == ADDRESSOF
+ /* If this varinfo represents a full variable just use it. */
+ && curr->is_full_var)
+ c->offset = 0;
+ else
+ c->offset = rhsoffset;
+ }
+ }
+
+
/* Given a COMPONENT_REF T, return the constraint_expr vector for it.
If address_p is true the result will be taken its address of. */
*************** get_constraint_for_component_ref (tree t
*** 2714,2728 ****
/* Pretend to take the address of the base, we'll take care of
adding the required subset of sub-fields below. */
get_constraint_for_1 (t, results, true);
- result = VEC_last (ce_s, *results);
-
gcc_assert (VEC_length (ce_s, *results) == 1);
/* This can also happen due to weird offsetof type macros. */
if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
result->type = SCALAR;
! if (result->type == SCALAR)
{
/* In languages like C, you can access one past the end of an
array. You aren't allowed to dereference it, so we can
--- 2847,2864 ----
/* Pretend to take the address of the base, we'll take care of
adding the required subset of sub-fields below. */
get_constraint_for_1 (t, results, true);
gcc_assert (VEC_length (ce_s, *results) == 1);
+ result = VEC_last (ce_s, *results);
/* This can also happen due to weird offsetof type macros. */
if (TREE_CODE (t) != ADDR_EXPR && result->type == ADDRESSOF)
result->type = SCALAR;
! if (result->type == SCALAR
! && get_varinfo (result->var)->is_full_var)
! /* For single-field vars do not bother about the offset. */
! result->offset = 0;
! else if (result->type == SCALAR)
{
/* In languages like C, you can access one past the end of an
array. You aren't allowed to dereference it, so we can
*************** get_constraint_for_component_ref (tree t
*** 2751,2762 ****
break;
}
}
! /* assert that we found *some* field there. The user couldn't be
! accessing *only* padding. */
! /* Still the user could access one past the end of an array
! embedded in a struct resulting in accessing *only* padding. */
! gcc_assert (VEC_length (ce_s, *results) >= 1
! || ref_contains_array_ref (orig_t));
}
else if (bitmaxsize == 0)
{
--- 2887,2911 ----
break;
}
}
! /* If we are going to take the address of this field then
! to be able to compute reachability correctly add at least
! the last field of the variable. */
! if (address_p
! && VEC_length (ce_s, *results) == 0)
! {
! curr = get_varinfo (cexpr.var);
! while (curr->next != NULL)
! curr = curr->next;
! cexpr.var = curr->id;
! VEC_safe_push (ce_s, heap, *results, &cexpr);
! }
! else
! /* Assert that we found *some* field there. The user couldn't be
! accessing *only* padding. */
! /* Still the user could access one past the end of an array
! embedded in a struct resulting in accessing *only* padding. */
! gcc_assert (VEC_length (ce_s, *results) >= 1
! || ref_contains_array_ref (orig_t));
}
else if (bitmaxsize == 0)
{
*************** get_constraint_for_1 (tree t, VEC (ce_s,
*** 2900,2923 ****
VEC_safe_push (ce_s, heap, *results, &temp);
return;
}
- else
- {
- temp.var = anything_id;
- temp.type = SCALAR;
- temp.offset = 0;
- VEC_safe_push (ce_s, heap, *results, &temp);
- return;
- }
break;
! default:
! {
! temp.type = ADDRESSOF;
! temp.var = anything_id;
! temp.offset = 0;
! VEC_safe_push (ce_s, heap, *results, &temp);
! return;
! }
}
}
case tcc_reference:
{
--- 3049,3058 ----
VEC_safe_push (ce_s, heap, *results, &temp);
return;
}
break;
! default:;
}
+ break;
}
case tcc_reference:
{
*************** get_constraint_for_1 (tree t, VEC (ce_s,
*** 2934,2948 ****
case COMPONENT_REF:
get_constraint_for_component_ref (t, results, address_p);
return;
! default:
! {
! temp.type = ADDRESSOF;
! temp.var = anything_id;
! temp.offset = 0;
! VEC_safe_push (ce_s, heap, *results, &temp);
! return;
! }
}
}
case tcc_unary:
{
--- 3069,3077 ----
case COMPONENT_REF:
get_constraint_for_component_ref (t, results, address_p);
return;
! default:;
}
+ break;
}
case tcc_unary:
{
*************** get_constraint_for_1 (tree t, VEC (ce_s,
*** 2963,2977 ****
/* FALLTHRU */
}
! default:
! {
! temp.type = ADDRESSOF;
! temp.var = anything_id;
! temp.offset = 0;
! VEC_safe_push (ce_s, heap, *results, &temp);
! return;
! }
}
}
case tcc_exceptional:
{
--- 3092,3110 ----
/* FALLTHRU */
}
! default:;
}
+ break;
+ }
+ case tcc_binary:
+ {
+ if (TREE_CODE (t) == POINTER_PLUS_EXPR)
+ {
+ get_constraint_for_ptr_offset (TREE_OPERAND (t, 0),
+ TREE_OPERAND (t, 1), results);
+ return;
+ }
+ break;
}
case tcc_exceptional:
{
*************** get_constraint_for_1 (tree t, VEC (ce_s,
*** 2982,3018 ****
get_constraint_for_1 (PHI_RESULT (t), results, address_p);
return;
}
- break;
case SSA_NAME:
{
get_constraint_for_ssa_var (t, results, address_p);
return;
}
! break;
! default:
! {
! temp.type = ADDRESSOF;
! temp.var = anything_id;
! temp.offset = 0;
! VEC_safe_push (ce_s, heap, *results, &temp);
! return;
! }
}
}
case tcc_declaration:
{
get_constraint_for_ssa_var (t, results, address_p);
return;
}
! default:
! {
! temp.type = ADDRESSOF;
! temp.var = anything_id;
! temp.offset = 0;
! VEC_safe_push (ce_s, heap, *results, &temp);
! return;
! }
}
}
/* Given a gimple tree T, return the constraint expression vector for it. */
--- 3115,3142 ----
get_constraint_for_1 (PHI_RESULT (t), results, address_p);
return;
}
case SSA_NAME:
{
get_constraint_for_ssa_var (t, results, address_p);
return;
}
! default:;
}
+ break;
}
case tcc_declaration:
{
get_constraint_for_ssa_var (t, results, address_p);
return;
}
! default:;
}
+
+ /* The default fallback is a constraint from anything. */
+ temp.type = ADDRESSOF;
+ temp.var = anything_id;
+ temp.offset = 0;
+ VEC_safe_push (ce_s, heap, *results, &temp);
}
/* Given a gimple tree T, return the constraint expression vector for it. */
*************** do_structure_copy (tree lhsop, tree rhso
*** 3298,3377 ****
}
}
-
- /* Handle pointer arithmetic EXPR when creating aliasing constraints.
- Expressions of the type PTR + CST can be handled in two ways:
-
- 1- If the constraint for PTR is ADDRESSOF for a non-structure
- variable, then we can use it directly because adding or
- subtracting a constant may not alter the original ADDRESSOF
- constraint (i.e., pointer arithmetic may not legally go outside
- an object's boundaries).
-
- 2- If the constraint for PTR is ADDRESSOF for a structure variable,
- then if CST is a compile-time constant that can be used as an
- offset, we can determine which sub-variable will be pointed-to
- by the expression.
-
- Return true if the expression is handled. For any other kind of
- expression, return false so that each operand can be added as a
- separate constraint by the caller. */
-
- static bool
- handle_ptr_arith (VEC (ce_s, heap) *lhsc, tree expr)
- {
- tree op0, op1;
- struct constraint_expr *c, *c2;
- unsigned int i = 0;
- unsigned int j = 0;
- VEC (ce_s, heap) *temp = NULL;
- unsigned HOST_WIDE_INT rhsunitoffset, rhsoffset;
-
- if (TREE_CODE (expr) != POINTER_PLUS_EXPR)
- return false;
-
- op0 = TREE_OPERAND (expr, 0);
- op1 = TREE_OPERAND (expr, 1);
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (op0)));
-
- /* If the offset is not a non-negative integer constant that fits
- in a HOST_WIDE_INT, we cannot handle it here. */
- if (!host_integerp (op1, 1))
- return false;
-
- /* Make sure the bit-offset also fits. */
- rhsunitoffset = TREE_INT_CST_LOW (op1);
- rhsoffset = rhsunitoffset * BITS_PER_UNIT;
- if (rhsunitoffset != rhsoffset / BITS_PER_UNIT)
- return false;
-
- get_constraint_for (op0, &temp);
-
- for (i = 0; VEC_iterate (ce_s, lhsc, i, c); i++)
- for (j = 0; VEC_iterate (ce_s, temp, j, c2); j++)
- {
- if (c2->type == ADDRESSOF && rhsoffset != 0)
- {
- varinfo_t temp = get_varinfo (c2->var);
-
- /* An access one after the end of an array is valid,
- so simply punt on accesses we cannot resolve. */
- temp = first_vi_for_offset (temp, rhsoffset);
- if (temp == NULL)
- continue;
- c2->var = temp->id;
- c2->offset = 0;
- }
- else
- c2->offset = rhsoffset;
- process_constraint (new_constraint (*c, *c2));
- }
-
- VEC_free (ce_s, heap, temp);
-
- return true;
- }
-
/* Create a constraint ID = OP. */
static void
--- 3422,3427 ----
*************** find_func_aliases (tree origt)
*** 3771,3859 ****
}
}
}
! /* Otherwise, just a regular assignment statement. */
! else if (TREE_CODE (t) == GIMPLE_MODIFY_STMT)
{
tree lhsop = GIMPLE_STMT_OPERAND (t, 0);
tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
- int i;
! if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
! && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
! {
! do_structure_copy (lhsop, rhsop);
! }
else
{
! /* Only care about operations with pointers, structures
! containing pointers, dereferences, and call expressions. */
! if (could_have_pointers (lhsop)
! || TREE_CODE (rhsop) == CALL_EXPR)
{
! get_constraint_for (lhsop, &lhsc);
! switch (TREE_CODE_CLASS (TREE_CODE (rhsop)))
! {
! /* RHS that consist of unary operations,
! exceptional types, or bare decls/constants, get
! handled directly by get_constraint_for. */
! case tcc_reference:
! case tcc_declaration:
! case tcc_constant:
! case tcc_exceptional:
! case tcc_expression:
! case tcc_vl_exp:
! case tcc_unary:
! {
! unsigned int j;
!
! get_constraint_for (rhsop, &rhsc);
! 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));
! }
!
! }
! break;
! case tcc_binary:
! {
! /* For pointer arithmetic of the form
! PTR + CST, we can simply use PTR's
! constraint because pointer arithmetic is
! not allowed to go out of bounds. */
! if (handle_ptr_arith (lhsc, rhsop))
! break;
! }
! /* FALLTHRU */
!
! /* Otherwise, walk each operand. Notice that we
! can't use the operand interface because we need
! to process expressions other than simple operands
! (e.g. INDIRECT_REF, ADDR_EXPR, CALL_EXPR). */
! default:
! for (i = 0; i < TREE_OPERAND_LENGTH (rhsop); i++)
! {
! tree op = TREE_OPERAND (rhsop, i);
! unsigned int j;
!
! gcc_assert (VEC_length (ce_s, rhsc) == 0);
! get_constraint_for (op, &rhsc);
! for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
! {
! struct constraint_expr *c2;
! while (VEC_length (ce_s, rhsc) > 0)
! {
! c2 = VEC_last (ce_s, rhsc);
! process_constraint (new_constraint (*c, *c2));
! VEC_pop (ce_s, rhsc);
! }
! }
! }
! }
}
}
}
--- 3821,3849 ----
}
}
}
! /* Otherwise, just a regular assignment statement. Only care about
! operations with pointer result, others are dealt with as escape
! points if they have pointer operands. */
! else if (TREE_CODE (t) == GIMPLE_MODIFY_STMT
! && could_have_pointers (GIMPLE_STMT_OPERAND (t, 0)))
{
tree lhsop = GIMPLE_STMT_OPERAND (t, 0);
tree rhsop = GIMPLE_STMT_OPERAND (t, 1);
! if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop)))
! do_structure_copy (lhsop, rhsop);
else
{
! unsigned int j;
! get_constraint_for (lhsop, &lhsc);
! get_constraint_for (rhsop, &rhsc);
! 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));
}
}
}
*************** create_function_info_for (tree decl, con
*** 4222,4229 ****
stats.total_vars++;
/* If it's varargs, we don't know how many arguments it has, so we
! can't do much.
! */
if (is_varargs)
{
vi->fullsize = ~0;
--- 4212,4218 ----
stats.total_vars++;
/* If it's varargs, we don't know how many arguments it has, so we
! can't do much. */
if (is_varargs)
{
vi->fullsize = ~0;
*************** create_function_info_for (tree decl, con
*** 4257,4262 ****
--- 4246,4252 ----
VEC_safe_push (varinfo_t, heap, varmap, argvi);
argvi->offset = i;
argvi->size = 1;
+ argvi->is_full_var = true;
argvi->fullsize = vi->fullsize;
insert_into_field_list_sorted (vi, argvi);
stats.total_vars ++;
*************** create_function_info_for (tree decl, con
*** 4293,4298 ****
--- 4283,4289 ----
resultvi->offset = i;
resultvi->size = 1;
resultvi->fullsize = vi->fullsize;
+ resultvi->is_full_var = true;
insert_into_field_list_sorted (vi, resultvi);
stats.total_vars ++;
if (DECL_RESULT (decl))
*************** create_variable_info_for (tree decl, con
*** 4411,4416 ****
--- 4402,4408 ----
vi->is_unknown_size_var = 1;
vi->fullsize = ~0;
vi->size = ~0;
+ vi->is_full_var = true;
VEC_free (fieldoff_s, heap, fieldstack);
return index;
}
*************** create_variable_info_for (tree decl, con
*** 4447,4452 ****
--- 4439,4446 ----
stats.total_vars++;
}
}
+ else
+ vi->is_full_var = true;
VEC_free (fieldoff_s, heap, fieldstack);
*************** init_base_vars (void)
*** 5198,5203 ****
--- 5192,5199 ----
static void
init_alias_vars (void)
{
+ use_field_sensitive = (MAX_FIELDS_FOR_FIELD_SENSITIVE > 1);
+
bitmap_obstack_initialize (&pta_obstack);
bitmap_obstack_initialize (&oldpta_obstack);
bitmap_obstack_initialize (&predbitmap_obstack);
Index: trunk/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/torture/pta-ptrarith-1.c 2008-07-07 13:48:47.000000000 +0200
***************
*** 0 ****
--- 1,33 ----
+ /* { dg-do run } */
+ /* { dg-options "-fdump-tree-alias" } */
+ /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+ struct Foo {
+ int *p;
+ };
+
+ void __attribute__((noinline))
+ foo (void *p)
+ {
+ struct Foo *f = (struct Foo *)p - 1;
+ *f->p = 0;
+ }
+
+ int bar (void)
+ {
+ struct Foo f;
+ int i = 1;
+ f.p = &i;
+ foo (&f + 1);
+ return i;
+ }
+ extern void abort (void);
+ int main()
+ {
+ if (bar () != 0)
+ abort ();
+ return 0;
+ }
+
+ /* { dg-final { scan-tree-dump "ESCAPED = { ESCAPED NONLOCAL f .* i }" "alias" } } */
+ /* { dg-final { cleanup-tree-dump "alias" } } */
Index: trunk/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/torture/ipa-pta-1.c 2008-07-07 13:48:47.000000000 +0200
***************
*** 0 ****
--- 1,40 ----
+ /* { dg-do compile } */
+ /* { dg-options "-fipa-pta -fdump-ipa-pta" } */
+ /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+ struct X { char x; char y; };
+
+ void bar (char *p);
+
+ void test1 (char a, char b, char c, char d, char e, char f, char g, char h)
+ {
+ char *p = &a;
+ p++;
+ bar (p);
+ }
+
+ void test2 (struct X a, char b, char c, char d, char e, char f, char g, char h)
+ {
+ char *p = &a.x;
+ p++;
+ bar (p);
+ }
+
+ void test3 (struct X a, char b, char c, char d, char e, char f, char g, char h)
+ {
+ char *p = &a.y;
+ bar (p);
+ }
+
+ void test4 (int a, char b, char c, char d, char e, char f, char g, char h)
+ {
+ char *p = (char *)&a;
+ p++;
+ p++;
+ p++;
+ p++;
+ bar (p);
+ }
+
+ /* { dg-final { scan-ipa-dump "bar.arg0 = { test4.arg0 test3.arg0 test2.arg0 test1.arg0 }" "pta" } } */
+ /* { dg-final { cleanup-ipa-dump "pta" } } */
Index: trunk/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- trunk/gcc/testsuite/gcc.dg/torture/pta-ptrarith-2.c 2008-07-07 14:15:36.000000000 +0200
***************
*** 0 ****
--- 1,36 ----
+ /* { dg-do run } */
+ /* { dg-options "-fdump-tree-alias" } */
+ /* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
+
+ struct Foo {
+ int **p;
+ int **q;
+ };
+
+ int __attribute__((noinline))
+ bar (void)
+ {
+ struct Foo f;
+ int j, i = 1;
+ char *p;
+ int *x = &i;
+ int *y = &j;
+ f.p = &y;
+ f.q = &x;
+ p = (char *)&f;
+ for (j = 0; j < sizeof (int *); ++j)
+ p++;
+ return ***(int ***)p;
+ }
+ extern void abort (void);
+ int main()
+ {
+ if (bar () != 1)
+ abort ();
+ return 0;
+ }
+
+ /* In theory = { i } is the correct solution. But it's not easy to scan
+ for that reliably, so just use what we create now. */
+ /* { dg-final { scan-tree-dump "= { i j }" "alias" } } */
+ /* { dg-final { cleanup-tree-dump "alias" } } */
More information about the Gcc-patches
mailing list