Commit 31de5b77 by Richard Guenther Committed by Richard Biener

tree-flow-inline.h (var_can_have_subvars): Move ...

2008-05-08  Richard Guenther  <rguenther@suse.de>

	* tree-flow-inline.h (var_can_have_subvars): Move ...
	* tree-ssa-structalias.c (var_can_have_subvars): ... here.
	* tree-flow.h (var_can_have_subvars): Remove.
	(push_fields_onto_fieldstack): Remove.
	(sort_fieldstack): Likewise.
	(struct fieldoff): Move ...
	* tree-ssa-structalias.c (struct fieldoff): ... here.  Remove
	alias_set and base_for_components fields.
	(sort_fieldstack): Make static.
	(push_fields_onto_fieldstack): Likewise.  Remove code that
	handles anything but RECORD_TYPEs.  Remove alias_set and
	base_for_components handling.
	(create_variable_info_for): Adjust.

From-SVN: r135110
parent 3ee6cb3f
2008-05-08 Richard Guenther <rguenther@suse.de>
* tree-flow-inline.h (var_can_have_subvars): Move ...
* tree-ssa-structalias.c (var_can_have_subvars): ... here.
* tree-flow.h (var_can_have_subvars): Remove.
(push_fields_onto_fieldstack): Remove.
(sort_fieldstack): Likewise.
(struct fieldoff): Move ...
* tree-ssa-structalias.c (struct fieldoff): ... here. Remove
alias_set and base_for_components fields.
(sort_fieldstack): Make static.
(push_fields_onto_fieldstack): Likewise. Remove code that
handles anything but RECORD_TYPEs. Remove alias_set and
base_for_components handling.
(create_variable_info_for): Adjust.
2008-05-08 Seongbae Park <seongbae.park@gmail.com>
* common.opt (Wframe-larger-than=): Shorten the help message
......
......@@ -1581,36 +1581,6 @@ ref_contains_array_ref (const_tree ref)
return false;
}
/* Return true if V is a tree that we can have subvars for.
Normally, this is any aggregate type. Also complex
types which are not gimple registers can have subvars. */
static inline bool
var_can_have_subvars (const_tree v)
{
/* Volatile variables should never have subvars. */
if (TREE_THIS_VOLATILE (v))
return false;
/* Non decls or memory tags can never have subvars. */
if (!DECL_P (v) || MTAG_P (v))
return false;
/* Aggregates can have subvars. */
if (AGGREGATE_TYPE_P (TREE_TYPE (v)))
return true;
/* Complex types variables which are not also a gimple register can
have subvars. */
if (TREE_CODE (TREE_TYPE (v)) == COMPLEX_TYPE
&& !DECL_GIMPLE_REG_P (v))
return true;
return false;
}
/* Return true, if the two ranges [POS1, SIZE1] and [POS2, SIZE2]
overlap. SIZE1 and/or SIZE2 can be (unsigned)-1 in which case the
range is open-ended. Otherwise return false. */
......
......@@ -854,7 +854,6 @@ static inline bool ref_contains_array_ref (const_tree);
static inline bool array_ref_contains_indirect_ref (const_tree);
extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
HOST_WIDE_INT *, HOST_WIDE_INT *);
static inline bool var_can_have_subvars (const_tree);
extern tree create_tag_raw (enum tree_code, tree, const char *);
extern void delete_mem_ref_stats (struct function *);
extern void dump_mem_ref_stats (FILE *);
......@@ -1169,39 +1168,6 @@ rtx addr_for_mem_ref (struct mem_address *, bool);
void get_address_description (tree, struct mem_address *);
tree maybe_fold_tmr (tree);
/* This structure is used during pushing fields onto the fieldstack
to track the offset of the field, since bitpos_of_field gives it
relative to its immediate containing type, and we want it relative
to the ultimate containing object. */
struct fieldoff
{
/* Type of the field. */
tree type;
/* Size, in bits, of the field. */
tree size;
/* Field. */
tree decl;
/* Offset from the base of the base containing object to this field. */
HOST_WIDE_INT offset;
/* Alias set for the field. */
alias_set_type alias_set;
/* True, if this offset can be a base for further component accesses. */
unsigned base_for_components : 1;
};
typedef struct fieldoff fieldoff_s;
DEF_VEC_O(fieldoff_s);
DEF_VEC_ALLOC_O(fieldoff_s,heap);
int push_fields_onto_fieldstack (tree, VEC(fieldoff_s,heap) **,
HOST_WIDE_INT, bool *, tree);
void sort_fieldstack (VEC(fieldoff_s,heap) *);
void init_alias_heapvars (void);
void delete_alias_heapvars (void);
unsigned int execute_fixup_cfg (void);
......
......@@ -3994,6 +3994,30 @@ insert_into_field_list_sorted (varinfo_t base, varinfo_t field)
}
}
/* This structure is used during pushing fields onto the fieldstack
to track the offset of the field, since bitpos_of_field gives it
relative to its immediate containing type, and we want it relative
to the ultimate containing object. */
struct fieldoff
{
/* Type of the field. */
tree type;
/* Size, in bits, of the field. */
tree size;
/* Field. */
tree decl;
/* Offset from the base of the base containing object to this field. */
HOST_WIDE_INT offset;
};
typedef struct fieldoff fieldoff_s;
DEF_VEC_O(fieldoff_s);
DEF_VEC_ALLOC_O(fieldoff_s,heap);
/* qsort comparison function for two fieldoff's PA and PB */
static int
......@@ -4012,7 +4036,7 @@ fieldoff_compare (const void *pa, const void *pb)
}
/* Sort a fieldstack according to the field offset and sizes. */
void
static void
sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
{
qsort (VEC_address (fieldoff_s, fieldstack),
......@@ -4021,6 +4045,28 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
fieldoff_compare);
}
/* Return true if V is a tree that we can have subvars for.
Normally, this is any aggregate type. Also complex
types which are not gimple registers can have subvars. */
static inline bool
var_can_have_subvars (const_tree v)
{
/* Volatile variables should never have subvars. */
if (TREE_THIS_VOLATILE (v))
return false;
/* Non decls or memory tags can never have subvars. */
if (!DECL_P (v) || MTAG_P (v))
return false;
/* Aggregates without overlapping fields can have subvars. */
if (TREE_CODE (TREE_TYPE (v)) == RECORD_TYPE)
return true;
return false;
}
/* Given a TYPE, and a vector of field offsets FIELDSTACK, push all
the fields of TYPE onto fieldstack, recording their offsets along
the way.
......@@ -4030,172 +4076,63 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
Returns the number of fields pushed.
HAS_UNION is set to true if we find a union type as a field of
TYPE.
ADDRESSABLE_TYPE is the type of the outermost object that could
have its address taken. */
TYPE. */
int
static int
push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
HOST_WIDE_INT offset, bool *has_union,
tree addressable_type)
HOST_WIDE_INT offset, bool *has_union)
{
tree field;
int count = 0;
unsigned int first_element = VEC_length (fieldoff_s, *fieldstack);
if (TREE_CODE (type) != RECORD_TYPE)
return 0;
/* If the vector of fields is growing too big, bail out early.
Callers check for VEC_length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make
sure this fails. */
if (first_element > MAX_FIELDS_FOR_FIELD_SENSITIVE)
if (VEC_length (fieldoff_s, *fieldstack) > MAX_FIELDS_FOR_FIELD_SENSITIVE)
return 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;
real_part->alias_set = -1;
real_part->base_for_components = false;
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;
img_part->alias_set = -1;
img_part->base_for_components = false;
count = 2;
}
else 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,
(TYPE_NONALIASED_COMPONENT (type)
? addressable_type
: TREE_TYPE (type)))))
/* 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);
if (TYPE_NONALIASED_COMPONENT (type))
pair->alias_set = get_alias_set (addressable_type);
else
pair->alias_set = -1;
pair->base_for_components = false;
count++;
}
else
count += pushed;
}
}
else
{
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
bool push = false;
int pushed = 0;
if (has_union
&& (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
*has_union = true;
if (!var_can_have_subvars (field))
push = true;
else if (!(pushed = push_fields_onto_fieldstack
(TREE_TYPE (field),
fieldstack,
offset + bitpos_of_field (field),
has_union))
&& (DECL_SIZE (field)
&& !integer_zerop (DECL_SIZE (field))))
/* 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)
{
bool push = false;
int pushed = 0;
if (has_union
&& (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
*has_union = true;
if (!var_can_have_subvars (field))
push = true;
else if (!(pushed = push_fields_onto_fieldstack
(TREE_TYPE (field),
fieldstack,
offset + bitpos_of_field (field),
has_union,
(DECL_NONADDRESSABLE_P (field)
? addressable_type
: TREE_TYPE (field))))
&& ((DECL_SIZE (field)
&& !integer_zerop (DECL_SIZE (field)))
|| (!DECL_SIZE (field)
&& TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE)))
/* 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. Trailing flexible
array members also need a representative to be able to
treat taking their address in PTA. */
push = true;
if (push)
{
fieldoff_s *pair;
pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
pair->type = TREE_TYPE (field);
pair->size = DECL_SIZE (field);
pair->decl = field;
pair->offset = offset + bitpos_of_field (field);
if (DECL_NONADDRESSABLE_P (field))
pair->alias_set = get_alias_set (addressable_type);
else
pair->alias_set = -1;
pair->base_for_components = false;
count++;
}
else
count += pushed;
}
}
/* Make sure the first pushed field is marked as eligible for
being a base for component references. */
if (count > 0)
VEC_index (fieldoff_s, *fieldstack, first_element)->base_for_components = true;
fieldoff_s *pair;
pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
pair->type = TREE_TYPE (field);
pair->size = DECL_SIZE (field);
pair->decl = field;
pair->offset = offset + bitpos_of_field (field);
count++;
}
else
count += pushed;
}
return count;
}
......@@ -4389,8 +4326,7 @@ create_variable_info_for (tree decl, const char *name)
|| TREE_CODE (decltype) == QUAL_UNION_TYPE;
if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
{
push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion,
decltype);
push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion);
if (hasunion)
{
VEC_free (fieldoff_s, heap, fieldstack);
......@@ -4398,7 +4334,6 @@ create_variable_info_for (tree decl, const char *name)
}
}
/* If the variable doesn't have subvars, we may end up needing to
sort the field list and create fake variables for all the
fields. */
......
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