#include "timevar.h"
#include "alloc-pool.h"
#include "splay-tree.h"
+#include "params.h"
#include "tree-ssa-structalias.h"
#include "cgraph.h"
typedef struct constraint_expr ce_s;
DEF_VEC_O(ce_s);
DEF_VEC_ALLOC_O(ce_s, heap);
-static void get_constraint_for (tree, VEC(ce_s, heap) **, bool *);
+static void get_constraint_for (tree, VEC(ce_s, heap) **);
static void do_deref (VEC (ce_s, heap) **);
/* Our set constraints are made up of two constraint expressions, one
graph->zero_weight_succs[from]);
}
- /* Merge all the non-zero weighted predecessor edges. */
+ /* Merge all the nonzero weighted predecessor edges. */
for (i = 0; VEC_iterate (constraint_edge_t, predvec, i, c); i++)
{
unsigned int d = c->dest;
}
- /* Merge all the non-zero weighted successor edges. */
+ /* Merge all the nonzero weighted successor edges. */
for (i = 0; VEC_iterate (constraint_edge_t, succvec, i, c); i++)
{
unsigned int d = c->dest;
int i = 0;
constraint_t c;
- graph = xmalloc (sizeof (struct constraint_graph));
- graph->succs = xcalloc (VEC_length (varinfo_t, varmap) + 1,
- sizeof (*graph->succs));
- graph->preds = xcalloc (VEC_length (varinfo_t, varmap) + 1,
- sizeof (*graph->preds));
- graph->zero_weight_succs = xcalloc (VEC_length (varinfo_t, varmap) + 1,
- sizeof (*graph->zero_weight_succs));
- graph->zero_weight_preds = xcalloc (VEC_length (varinfo_t, varmap) + 1,
- sizeof (*graph->zero_weight_preds));
+ graph = XNEW (struct constraint_graph);
+ graph->succs = XCNEWVEC (VEC(constraint_edge_t,heap) *, VEC_length (varinfo_t, varmap) + 1);
+ graph->preds = XCNEWVEC (VEC(constraint_edge_t,heap) *, VEC_length (varinfo_t, varmap) + 1);
+ graph->zero_weight_succs = XCNEWVEC (bitmap, VEC_length (varinfo_t, varmap) + 1);
+ graph->zero_weight_preds = XCNEWVEC (bitmap, VEC_length (varinfo_t, varmap) + 1);
for (i = 0; VEC_iterate (constraint_t, constraints, i, c); i++)
{
init_topo_info (void)
{
size_t size = VEC_length (varinfo_t, varmap);
- struct topo_info *ti = xmalloc (sizeof (struct topo_info));
+ struct topo_info *ti = XNEW (struct topo_info);
ti->visited = sbitmap_alloc (size);
sbitmap_zero (ti->visited);
ti->topo_order = VEC_alloc (unsigned, heap, 1);
return (get_varinfo (n)->offset + *offset) < get_varinfo (n)->fullsize;
}
-#define DONT_PROPAGATE_WITH_ANYTHING 0
-
/* Process a constraint C that represents *x = &y. */
static void
unsigned int j;
bitmap_iterator bi;
-#if DONT_PROPAGATE_WITH_ANYTHING
if (bitmap_bit_p (delta, anything_id))
{
flag = !bitmap_bit_p (sol, anything_id);
bitmap_set_bit (sol, anything_id);
goto done;
}
-#endif
/* For each variable j in delta (Sol(y)), add
an edge in the graph from j to x, and union Sol(j) into Sol(x). */
EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
fprintf (dump_file, "Untypesafe usage in do_sd_constraint\n");
}
-#if DONT_PROPAGATE_WITH_ANYTHING
+
done:
-#endif
/* If the LHS solution changed, mark the var as changed. */
if (flag)
{
unsigned int j;
bitmap_iterator bi;
-#if DONT_PROPAGATE_WITH_ANYTHING
if (bitmap_bit_p (sol, anything_id))
{
EXECUTE_IF_SET_IN_BITMAP (delta, 0, j, bi)
}
return;
}
-#endif
/* For each member j of delta (Sol(x)), add an edge from y to j and
union Sol(y) into Sol(j) */
static struct scc_info *
init_scc_info (void)
{
- struct scc_info *si = xmalloc (sizeof (struct scc_info));
+ struct scc_info *si = XNEW (struct scc_info);
size_t size = VEC_length (varinfo_t, varmap);
si->current_index = 0;
sbitmap_zero (si->visited);
si->in_component = sbitmap_alloc (size);
sbitmap_ones (si->in_component);
- si->visited_index = xcalloc (sizeof (unsigned int), size + 1);
+ si->visited_index = XCNEWVEC (unsigned int, size + 1);
si->scc_stack = VEC_alloc (unsigned, heap, 1);
si->unification_queue = VEC_alloc (unsigned, heap, 1);
return si;
finder.t = t;
slot = htab_find_slot (id_for_tree, &finder, INSERT);
gcc_assert (*slot == NULL);
- new_pair = xmalloc (sizeof (struct tree_id));
+ new_pair = XNEW (struct tree_id);
new_pair->t = t;
new_pair->id = id;
*slot = (void *)new_pair;
/* Given a COMPONENT_REF T, return the constraint_expr for it. */
static void
-get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results,
- bool *anyoffset)
+get_constraint_for_component_ref (tree t, VEC(ce_s, heap) **results)
{
tree orig_t = t;
HOST_WIDE_INT bitsize = -1;
}
t = get_ref_base_and_extent (t, &bitpos, &bitsize, &bitmaxsize);
- get_constraint_for (t, results, anyoffset);
+ get_constraint_for (t, results);
result = VEC_last (ce_s, *results);
+ result->offset = bitpos;
gcc_assert (beforelength + 1 == VEC_length (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 we know where this goes, then yay. Otherwise, booo. */
- if (bitmaxsize != -1
- && bitsize == bitmaxsize)
- {
- result->offset = bitpos;
- }
- /* FIXME: Handle the DEREF case. */
- else if (anyoffset && result->type != DEREF)
- {
- result->offset = 0;
- *anyoffset = true;
- }
- else
- {
- result->var = anything_id;
- result->offset = 0;
- }
-
+
if (result->type == SCALAR)
{
/* In languages like C, you can access one past the end of an
for (curr = get_varinfo (result->var); curr; curr = curr->next)
{
if (offset_overlaps_with_access (curr->offset, curr->size,
- result->offset, bitsize))
+ result->offset, bitmaxsize))
{
result->var = curr->id;
break;
/* Given a tree T, return the constraint expression for it. */
static void
-get_constraint_for (tree t, VEC (ce_s, heap) **results, bool *anyoffset)
+get_constraint_for (tree t, VEC (ce_s, heap) **results)
{
struct constraint_expr temp;
{
struct constraint_expr *c;
unsigned int i;
-
- get_constraint_for (TREE_OPERAND (t, 0), results, anyoffset);
+ tree exp = TREE_OPERAND (t, 0);
+ tree pttype = TREE_TYPE (TREE_TYPE (t));
+
+ get_constraint_for (exp, results);
+ /* Make sure we capture constraints to all elements
+ of an array. */
+ if ((handled_component_p (exp)
+ && ref_contains_array_ref (exp))
+ || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE)
+ {
+ struct constraint_expr *origrhs;
+ varinfo_t origvar;
+ struct constraint_expr tmp;
+
+ gcc_assert (VEC_length (ce_s, *results) == 1);
+ origrhs = VEC_last (ce_s, *results);
+ tmp = *origrhs;
+ VEC_pop (ce_s, *results);
+ origvar = get_varinfo (origrhs->var);
+ for (; origvar; origvar = origvar->next)
+ {
+ tmp.var = origvar->id;
+ VEC_safe_push (ce_s, heap, *results, &tmp);
+ }
+ }
+ else if (VEC_length (ce_s, *results) == 1
+ && (AGGREGATE_TYPE_P (pttype)
+ || TREE_CODE (pttype) == COMPLEX_TYPE))
+ {
+ struct constraint_expr *origrhs;
+ varinfo_t origvar;
+ struct constraint_expr tmp;
+
+ gcc_assert (VEC_length (ce_s, *results) == 1);
+ origrhs = VEC_last (ce_s, *results);
+ tmp = *origrhs;
+ VEC_pop (ce_s, *results);
+ origvar = get_varinfo (origrhs->var);
+ for (; origvar; origvar = origvar->next)
+ {
+ tmp.var = origvar->id;
+ VEC_safe_push (ce_s, heap, *results, &tmp);
+ }
+ }
+
for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
{
if (c->type == DEREF)
{
heapvar = create_tmp_var_raw (ptr_type_node, "HEAP");
DECL_EXTERNAL (heapvar) = 1;
- add_referenced_tmp_var (heapvar);
+ if (referenced_vars)
+ add_referenced_tmp_var (heapvar);
heapvar_insert (t, heapvar);
}
{
case INDIRECT_REF:
{
- get_constraint_for (TREE_OPERAND (t, 0), results, anyoffset);
+ get_constraint_for (TREE_OPERAND (t, 0), results);
do_deref (results);
return;
}
case ARRAY_REF:
case ARRAY_RANGE_REF:
case COMPONENT_REF:
- get_constraint_for_component_ref (t, results, anyoffset);
+ get_constraint_for_component_ref (t, results);
return;
default:
{
if (!(POINTER_TYPE_P (TREE_TYPE (t))
&& ! POINTER_TYPE_P (TREE_TYPE (op))))
{
- get_constraint_for (op, results, anyoffset);
+ get_constraint_for (op, results);
return;
}
{
case PHI_NODE:
{
- get_constraint_for (PHI_RESULT (t), results, anyoffset);
+ get_constraint_for (PHI_RESULT (t), results);
return;
}
break;
unsigned HOST_WIDE_INT lhssize;
unsigned HOST_WIDE_INT rhssize;
- get_constraint_for (lhsop, &lhsc, NULL);
- get_constraint_for (rhsop, &rhsc, NULL);
+ get_constraint_for (lhsop, &lhsc);
+ get_constraint_for (rhsop, &rhsc);
gcc_assert (VEC_length (ce_s, lhsc) == 1);
gcc_assert (VEC_length (ce_s, rhsc) == 1);
lhs = *(VEC_last (ce_s, lhsc));
bitmap addr_taken;
use_operand_p use_p;
ssa_op_iter iter;
- bool stmt_escapes_p = is_escape_site (stmt, ai);
+ enum escape_type stmt_escape_type = is_escape_site (stmt, ai);
tree op;
/* Mark all the variables whose address are taken by the statement. */
/* If STMT is an escape point, all the addresses taken by it are
call-clobbered. */
- if (stmt_escapes_p)
+ if (stmt_escape_type != NO_ESCAPE)
{
bitmap_iterator bi;
unsigned i;
EXECUTE_IF_SET_IN_BITMAP (addr_taken, 0, i, bi)
- mark_call_clobbered (referenced_var (i));
+ {
+ tree rvar = referenced_var (i);
+ if (!unmodifiable_var_p (rvar))
+ mark_call_clobbered (rvar, stmt_escape_type);
+ }
}
}
var = SSA_NAME_VAR (op);
v_ann = var_ann (var);
- /* If the operand's variable may be aliased, keep track of how
- many times we've referenced it. This is used for alias
- grouping in compute_flow_insensitive_aliasing. */
- if (may_be_aliased (var))
- NUM_REFERENCES_INC (v_ann);
+ /* The base variable of an ssa name must be a GIMPLE register, and thus
+ it cannot be aliased. */
+ gcc_assert (!may_be_aliased (var));
/* We are only interested in pointers. */
if (!POINTER_TYPE_P (TREE_TYPE (op)))
bitmap_set_bit (ai->dereferenced_ptrs_load, DECL_UID (var));
}
- if (stmt_escapes_p && num_derefs < num_uses)
+ if (stmt_escape_type != NO_ESCAPE && num_derefs < num_uses)
{
/* If STMT is an escape point and STMT contains at
least one direct use of OP, then the value of OP
escapes and so the pointed-to variables need to
be marked call-clobbered. */
pi->value_escapes_p = 1;
+ pi->escape_mask |= stmt_escape_type;
/* If the statement makes a function call, assume
that pointer OP will be dereferenced in a store
VEC (ce_s, heap) *temp = NULL;
unsigned int rhsoffset = 0;
- if (TREE_CODE (expr) != PLUS_EXPR)
+ if (TREE_CODE (expr) != PLUS_EXPR
+ && TREE_CODE (expr) != MINUS_EXPR)
return false;
op0 = TREE_OPERAND (expr, 0);
op1 = TREE_OPERAND (expr, 1);
- get_constraint_for (op0, &temp, NULL);
+ get_constraint_for (op0, &temp);
if (POINTER_TYPE_P (TREE_TYPE (op0))
- && TREE_CODE (TREE_TYPE (TREE_TYPE (op0))) == RECORD_TYPE
- && TREE_CODE (op1) == INTEGER_CST)
+ && TREE_CODE (op1) == INTEGER_CST
+ && TREE_CODE (expr) == PLUS_EXPR)
{
rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
}
if (c2->type == ADDRESSOF && rhsoffset != 0)
{
varinfo_t temp = get_varinfo (c2->var);
-
- gcc_assert (first_vi_for_offset (temp, rhsoffset) != NULL);
- c2->var = first_vi_for_offset (temp, rhsoffset)->id;
+
+ /* 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
/* Now build constraints expressions. */
if (TREE_CODE (t) == PHI_NODE)
{
+ gcc_assert (!AGGREGATE_TYPE_P (TREE_TYPE (PHI_RESULT (t))));
+
/* Only care about pointers and structures containing
pointers. */
if (POINTER_TYPE_P (TREE_TYPE (PHI_RESULT (t)))
- || AGGREGATE_TYPE_P (TREE_TYPE (PHI_RESULT (t))))
+ || TREE_CODE (TREE_TYPE (PHI_RESULT (t))) == COMPLEX_TYPE)
{
int i;
unsigned int j;
/* For a phi node, assign all the arguments to
the result. */
- get_constraint_for (PHI_RESULT (t), &lhsc, NULL);
+ get_constraint_for (PHI_RESULT (t), &lhsc);
for (i = 0; i < PHI_NUM_ARGS (t); i++)
{
- get_constraint_for (PHI_ARG_DEF (t, i), &rhsc, NULL);
+ tree rhstype;
+ tree strippedrhs = PHI_ARG_DEF (t, i);
+
+ STRIP_NOPS (strippedrhs);
+ rhstype = TREE_TYPE (strippedrhs);
+ get_constraint_for (PHI_ARG_DEF (t, i), &rhsc);
+
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
{
struct constraint_expr *c2;
tree lhsop;
tree rhsop;
unsigned int varid;
- bool found = false;
tree arglist;
varinfo_t fi;
int i = 1;
we should still be able to handle. */
if (decl)
{
- found = lookup_id_for_tree (decl, &varid);
- gcc_assert (found);
+ varid = get_id_for_tree (decl);
}
else
{
decl = TREE_OPERAND (rhsop, 0);
- found = lookup_id_for_tree (decl, &varid);
- gcc_assert (found);
+ varid = get_id_for_tree (decl);
}
/* Assign all the passed arguments to the appropriate incoming
struct constraint_expr lhs ;
struct constraint_expr *rhsp;
- get_constraint_for (arg, &rhsc, NULL);
+ get_constraint_for (arg, &rhsc);
if (TREE_CODE (decl) != FUNCTION_DECL)
{
lhs.type = DEREF;
struct constraint_expr *lhsp;
unsigned int j = 0;
- get_constraint_for (lhsop, &lhsc, NULL);
+ get_constraint_for (lhsop, &lhsc);
if (TREE_CODE (decl) != FUNCTION_DECL)
{
rhs.type = DEREF;
tree rhsop = TREE_OPERAND (t, 1);
int i;
- if (AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
- && AGGREGATE_TYPE_P (TREE_TYPE (rhsop)))
+ if ((AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
+ || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE)
+ && (AGGREGATE_TYPE_P (TREE_TYPE (rhsop))
+ || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE))
{
do_structure_copy (lhsop, rhsop);
}
containing pointers, dereferences, and call expressions. */
if (POINTER_TYPE_P (TREE_TYPE (lhsop))
|| AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
+ || TREE_CODE (TREE_TYPE (lhsop)) == COMPLEX_TYPE
|| TREE_CODE (rhsop) == CALL_EXPR)
{
- get_constraint_for (lhsop, &lhsc, NULL);
+ get_constraint_for (lhsop, &lhsc);
switch (TREE_CODE_CLASS (TREE_CODE (rhsop)))
{
/* RHS that consist of unary operations,
case tcc_unary:
{
unsigned int j;
- bool need_anyoffset = false;
- tree strippedrhs = rhsop;
- tree rhstype;
-
- /* XXX: Push this back into the ADDR_EXPR
- case, and remove anyoffset handling. */
- STRIP_NOPS (strippedrhs);
- rhstype = TREE_TYPE (strippedrhs);
-
- get_constraint_for (rhsop, &rhsc, &need_anyoffset);
- if (TREE_CODE (strippedrhs) == ADDR_EXPR
- && AGGREGATE_TYPE_P (TREE_TYPE (rhstype)))
- {
- struct constraint_expr *origrhs;
- varinfo_t origvar;
- struct constraint_expr tmp;
-
- gcc_assert (VEC_length (ce_s, rhsc) == 1);
- origrhs = VEC_last (ce_s, rhsc);
- tmp = *origrhs;
- VEC_pop (ce_s, rhsc);
- origvar = get_varinfo (origrhs->var);
- for (; origvar; origvar = origvar->next)
- {
- tmp.var = origvar->id;
- VEC_safe_push (ce_s, heap, rhsc, &tmp);
- }
- }
+ get_constraint_for (rhsop, &rhsc);
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
{
struct constraint_expr *c2;
unsigned int j;
gcc_assert (VEC_length (ce_s, rhsc) == 0);
- get_constraint_for (op, &rhsc, NULL);
+ get_constraint_for (op, &rhsc);
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
{
struct constraint_expr *c2;
}
+/* Insert the varinfo FIELD into the field list for BASE, at the front
+ of the list. */
+
+static void
+insert_into_field_list (varinfo_t base, varinfo_t field)
+{
+ varinfo_t prev = base;
+ varinfo_t curr = base->next;
+
+ field->next = curr;
+ prev->next = field;
+}
+
/* Insert the varinfo FIELD into the field list for BASE, ordered by
offset. */
static void
-insert_into_field_list (varinfo_t base, varinfo_t field)
+insert_into_field_list_sorted (varinfo_t base, varinfo_t field)
{
varinfo_t prev = base;
varinfo_t curr = base->next;
if (foa->offset != fob->offset)
return foa->offset - fob->offset;
- foasize = TREE_INT_CST_LOW (DECL_SIZE (foa->field));
- fobsize = TREE_INT_CST_LOW (DECL_SIZE (fob->field));
+ foasize = TREE_INT_CST_LOW (foa->size);
+ fobsize = TREE_INT_CST_LOW (fob->size);
return foasize - fobsize;
}
{
tree field;
int count = 0;
+
+ if (TREE_CODE (type) == COMPLEX_TYPE)
+ {
+ fieldoff_s *real_part, *img_part;
+ real_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+ real_part->type = TREE_TYPE (type);
+ real_part->size = TYPE_SIZE (TREE_TYPE (type));
+ real_part->offset = offset;
+ real_part->decl = NULL_TREE;
+
+ img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+ img_part->type = TREE_TYPE (type);
+ img_part->size = TYPE_SIZE (TREE_TYPE (type));
+ img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type)));
+ img_part->decl = NULL_TREE;
+
+ return 2;
+ }
+
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ tree sz = TYPE_SIZE (type);
+ tree elsz = TYPE_SIZE (TREE_TYPE (type));
+ HOST_WIDE_INT nr;
+ int i;
+
+ if (! sz
+ || ! host_integerp (sz, 1)
+ || TREE_INT_CST_LOW (sz) == 0
+ || ! elsz
+ || ! host_integerp (elsz, 1)
+ || TREE_INT_CST_LOW (elsz) == 0)
+ return 0;
+
+ nr = TREE_INT_CST_LOW (sz) / TREE_INT_CST_LOW (elsz);
+ if (nr > SALIAS_MAX_ARRAY_ELEMENTS)
+ return 0;
+
+ for (i = 0; i < nr; ++i)
+ {
+ bool push = false;
+ int pushed = 0;
+
+ if (has_union
+ && (TREE_CODE (TREE_TYPE (type)) == QUAL_UNION_TYPE
+ || TREE_CODE (TREE_TYPE (type)) == UNION_TYPE))
+ *has_union = true;
+
+ if (!AGGREGATE_TYPE_P (TREE_TYPE (type))) /* var_can_have_subvars */
+ push = true;
+ else if (!(pushed = push_fields_onto_fieldstack
+ (TREE_TYPE (type), fieldstack,
+ offset + i * TREE_INT_CST_LOW (elsz), has_union)))
+ /* Empty structures may have actual size, like in C++. So
+ see if we didn't push any subfields and the size is
+ nonzero, push the field onto the stack */
+ push = true;
+
+ if (push)
+ {
+ fieldoff_s *pair;
+
+ pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
+ pair->type = TREE_TYPE (type);
+ pair->size = elsz;
+ pair->decl = NULL_TREE;
+ pair->offset = offset + i * TREE_INT_CST_LOW (elsz);
+ count++;
+ }
+ else
+ count += pushed;
+ }
+
+ return count;
+ }
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
fieldoff_s *pair;
pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
- pair->field = field;
+ pair->type = TREE_TYPE (field);
+ pair->size = DECL_SIZE (field);
+ pair->decl = field;
pair->offset = offset + bitpos_of_field (field);
count++;
}
argvi->size = 1;
argvi->fullsize = vi->fullsize;
argvi->has_union = false;
- insert_into_field_list (vi, argvi);
+ insert_into_field_list_sorted (vi, argvi);
stats.total_vars ++;
if (arg)
{
arg = TREE_CHAIN (arg);
}
}
-
+
/* Create a variable for the return var. */
if (DECL_RESULT (decl) != NULL
|| !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
vi->fullsize ++;
-
if (DECL_RESULT (decl))
resultdecl = DECL_RESULT (decl);
resultvi->size = 1;
resultvi->fullsize = vi->fullsize;
resultvi->has_union = false;
- insert_into_field_list (vi, resultvi);
+ insert_into_field_list_sorted (vi, resultvi);
stats.total_vars ++;
if (DECL_RESULT (decl))
insert_id_for_tree (DECL_RESULT (decl), newindex);
}
return false;
}
-
/* Create a varinfo structure for NAME and DECL, and add it to VARMAP.
This will also create any varinfo structures necessary for fields
of DECL. */
if (use_field_sensitive
&& !notokay
&& !vi->is_unknown_size_var
- && var_can_have_subvars (decl))
+ && var_can_have_subvars (decl)
+ && VEC_length (fieldoff_s, fieldstack) <= MAX_FIELDS_FOR_FIELD_SENSITIVE)
{
unsigned int newindex = VEC_length (varinfo_t, varmap);
fieldoff_s *fo = NULL;
unsigned int i;
- tree field;
for (i = 0; !notokay && VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
{
- if (!DECL_SIZE (fo->field)
- || TREE_CODE (DECL_SIZE (fo->field)) != INTEGER_CST
+ if (! fo->size
+ || TREE_CODE (fo->size) != INTEGER_CST
|| fo->offset < 0)
{
notokay = true;
return index;
}
- field = fo->field;
- vi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
+ vi->size = TREE_INT_CST_LOW (fo->size);
vi->offset = fo->offset;
- for (i = 1; VEC_iterate (fieldoff_s, fieldstack, i, fo); i++)
+ for (i = VEC_length (fieldoff_s, fieldstack) - 1;
+ i >= 1 && VEC_iterate (fieldoff_s, fieldstack, i, fo);
+ i--)
{
varinfo_t newvi;
const char *newname;
char *tempname;
- field = fo->field;
newindex = VEC_length (varinfo_t, varmap);
- asprintf (&tempname, "%s.%s", vi->name, alias_get_name (field));
+ if (fo->decl)
+ asprintf (&tempname, "%s.%s", vi->name, alias_get_name (fo->decl));
+ else
+ asprintf (&tempname, "%s." HOST_WIDE_INT_PRINT_DEC, vi->name, fo->offset);
newname = ggc_strdup (tempname);
free (tempname);
newvi = new_var_info (decl, newindex, newname, newindex);
newvi->offset = fo->offset;
- newvi->size = TREE_INT_CST_LOW (DECL_SIZE (field));
+ newvi->size = TREE_INT_CST_LOW (fo->size);
newvi->fullsize = vi->fullsize;
insert_into_field_list (vi, newvi);
VEC_safe_push (varinfo_t, heap, varmap, newvi);
{
tree t;
- /* For each incoming argument arg, ARG = &ANYTHING */
+ /* For each incoming argument arg, ARG = &ANYTHING or a dummy variable if
+ flag_argument_noalias > 1. */
for (t = DECL_ARGUMENTS (current_function_decl); t; t = TREE_CHAIN (t))
{
struct constraint_expr lhs;
lhs.offset = 0;
lhs.type = SCALAR;
lhs.var = create_variable_info_for (t, alias_get_name (t));
-
- for (p = get_varinfo (lhs.var); p; p = p->next)
- make_constraint_to_anything (p);
- }
+ /* With flag_argument_noalias greater than one means that the incoming
+ argument cannot alias anything except for itself so create a HEAP
+ variable. */
+ if (POINTER_TYPE_P (TREE_TYPE (t))
+ && flag_argument_noalias > 1)
+ {
+ varinfo_t vi;
+ struct constraint_expr rhs;
+ tree heapvar = heapvar_lookup (t);
+ unsigned int id;
+ if (heapvar == NULL_TREE)
+ {
+ heapvar = create_tmp_var_raw (TREE_TYPE (TREE_TYPE (t)),
+ "PARM_NOALIAS");
+ DECL_EXTERNAL (heapvar) = 1;
+ if (referenced_vars)
+ add_referenced_tmp_var (heapvar);
+ heapvar_insert (t, heapvar);
+ }
+ id = create_variable_info_for (heapvar,
+ alias_get_name (heapvar));
+ vi = get_varinfo (id);
+ vi->is_artificial_var = 1;
+ vi->is_heap_var = 1;
+ rhs.var = id;
+ rhs.type = ADDRESSOF;
+ rhs.offset = 0;
+ for (p = get_varinfo (lhs.var); p; p = p->next)
+ {
+ struct constraint_expr temp = lhs;
+ temp.var = p->id;
+ process_constraint (new_constraint (temp, rhs));
+ }
+ }
+ else
+ for (p = get_varinfo (lhs.var); p; p = p->next)
+ make_constraint_to_anything (p);
+ }
}
/* Set bits in INTO corresponding to the variable uids in solution set
find_what_p_points_to (tree p)
{
unsigned int id = 0;
+ tree lookup_p = p;
if (!have_alias_info)
return false;
- if (lookup_id_for_tree (p, &id))
+ /* For parameters, get at the points-to set for the actual parm
+ decl. */
+ if (TREE_CODE (p) == SSA_NAME
+ && TREE_CODE (SSA_NAME_VAR (p)) == PARM_DECL
+ && default_def (SSA_NAME_VAR (p)) == p)
+ lookup_p = SSA_NAME_VAR (p);
+
+ if (lookup_id_for_tree (lookup_p, &id))
{
varinfo_t vi = get_varinfo (id);
gate_ipa_pta (void)
{
return (flag_unit_at_a_time != 0
+ && flag_ipa_pta
/* Don't bother doing anything if the program has errors. */
&& !(errorcount || sorrycount));
}
/* Execute the driver for IPA PTA. */
-static void
+static unsigned int
ipa_pta_execute (void)
{
struct cgraph_node *node;
in_ipa_mode = 1;
-
+ init_alias_heapvars ();
init_alias_vars ();
-
+
for (node = cgraph_nodes; node; node = node->next)
{
if (!node->analyzed || cgraph_is_master_clone (node))
if (dump_file)
dump_sa_points_to_info (dump_file);
in_ipa_mode = 0;
+ delete_alias_heapvars ();
+ delete_points_to_sets ();
+ return 0;
}
struct tree_opt_pass pass_ipa_pta =