#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
/* 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);
+
+ 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);
+ }
+ }
for (i = 0; VEC_iterate (ce_s, *results, i, c); i++)
{
if (c->type == DEREF)
{
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));
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)
{
rhsoffset = TREE_INT_CST_LOW (op1) * BITS_PER_UNIT;
/* 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);
+ get_constraint_for (PHI_ARG_DEF (t, i), &rhsc);
for (j = 0; VEC_iterate (ce_s, lhsc, j, c); j++)
{
struct constraint_expr *c2;
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;
|| AGGREGATE_TYPE_P (TREE_TYPE (lhsop))
|| 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;
STRIP_NOPS (strippedrhs);
rhstype = TREE_TYPE (strippedrhs);
- get_constraint_for (rhsop, &rhsc, &need_anyoffset);
+ get_constraint_for (rhsop, &rhsc);
if (TREE_CODE (strippedrhs) == ADDR_EXPR
- && AGGREGATE_TYPE_P (TREE_TYPE (rhstype)))
+ && AGGREGATE_TYPE_P (TREE_TYPE (rhstype))
+ && VEC_length (ce_s, rhsc) == 1)
{
struct constraint_expr *origrhs;
varinfo_t origvar;
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;
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)
{