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> 2008-05-08 Seongbae Park <seongbae.park@gmail.com>
* common.opt (Wframe-larger-than=): Shorten the help message * common.opt (Wframe-larger-than=): Shorten the help message
......
...@@ -1581,36 +1581,6 @@ ref_contains_array_ref (const_tree ref) ...@@ -1581,36 +1581,6 @@ ref_contains_array_ref (const_tree ref)
return false; 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] /* Return true, if the two ranges [POS1, SIZE1] and [POS2, SIZE2]
overlap. SIZE1 and/or SIZE2 can be (unsigned)-1 in which case the overlap. SIZE1 and/or SIZE2 can be (unsigned)-1 in which case the
range is open-ended. Otherwise return false. */ range is open-ended. Otherwise return false. */
......
...@@ -854,7 +854,6 @@ static inline bool ref_contains_array_ref (const_tree); ...@@ -854,7 +854,6 @@ static inline bool ref_contains_array_ref (const_tree);
static inline bool array_ref_contains_indirect_ref (const_tree); static inline bool array_ref_contains_indirect_ref (const_tree);
extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *, extern tree get_ref_base_and_extent (tree, HOST_WIDE_INT *,
HOST_WIDE_INT *, 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 tree create_tag_raw (enum tree_code, tree, const char *);
extern void delete_mem_ref_stats (struct function *); extern void delete_mem_ref_stats (struct function *);
extern void dump_mem_ref_stats (FILE *); extern void dump_mem_ref_stats (FILE *);
...@@ -1169,39 +1168,6 @@ rtx addr_for_mem_ref (struct mem_address *, bool); ...@@ -1169,39 +1168,6 @@ rtx addr_for_mem_ref (struct mem_address *, bool);
void get_address_description (tree, struct mem_address *); void get_address_description (tree, struct mem_address *);
tree maybe_fold_tmr (tree); 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 init_alias_heapvars (void);
void delete_alias_heapvars (void); void delete_alias_heapvars (void);
unsigned int execute_fixup_cfg (void); unsigned int execute_fixup_cfg (void);
......
...@@ -3994,6 +3994,30 @@ insert_into_field_list_sorted (varinfo_t base, varinfo_t field) ...@@ -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 */ /* qsort comparison function for two fieldoff's PA and PB */
static int static int
...@@ -4012,7 +4036,7 @@ fieldoff_compare (const void *pa, const void *pb) ...@@ -4012,7 +4036,7 @@ fieldoff_compare (const void *pa, const void *pb)
} }
/* Sort a fieldstack according to the field offset and sizes. */ /* Sort a fieldstack according to the field offset and sizes. */
void static void
sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack) sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
{ {
qsort (VEC_address (fieldoff_s, fieldstack), qsort (VEC_address (fieldoff_s, fieldstack),
...@@ -4021,6 +4045,28 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack) ...@@ -4021,6 +4045,28 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
fieldoff_compare); 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 /* Given a TYPE, and a vector of field offsets FIELDSTACK, push all
the fields of TYPE onto fieldstack, recording their offsets along the fields of TYPE onto fieldstack, recording their offsets along
the way. the way.
...@@ -4030,172 +4076,63 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack) ...@@ -4030,172 +4076,63 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
Returns the number of fields pushed. Returns the number of fields pushed.
HAS_UNION is set to true if we find a union type as a field of HAS_UNION is set to true if we find a union type as a field of
TYPE. TYPE. */
ADDRESSABLE_TYPE is the type of the outermost object that could
have its address taken. */
int static int
push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
HOST_WIDE_INT offset, bool *has_union, HOST_WIDE_INT offset, bool *has_union)
tree addressable_type)
{ {
tree field; tree field;
int count = 0; 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. /* If the vector of fields is growing too big, bail out early.
Callers check for VEC_length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make Callers check for VEC_length <= MAX_FIELDS_FOR_FIELD_SENSITIVE, make
sure this fails. */ sure this fails. */
if (first_element > MAX_FIELDS_FOR_FIELD_SENSITIVE) if (VEC_length (fieldoff_s, *fieldstack) > MAX_FIELDS_FOR_FIELD_SENSITIVE)
return 0; return 0;
if (TREE_CODE (type) == COMPLEX_TYPE) for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{ if (TREE_CODE (field) == FIELD_DECL)
fieldoff_s *real_part, *img_part; {
real_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL); bool push = false;
real_part->type = TREE_TYPE (type); int pushed = 0;
real_part->size = TYPE_SIZE (TREE_TYPE (type));
real_part->offset = offset; if (has_union
real_part->decl = NULL_TREE; && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
real_part->alias_set = -1; || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
real_part->base_for_components = false; *has_union = true;
img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL); if (!var_can_have_subvars (field))
img_part->type = TREE_TYPE (type); push = true;
img_part->size = TYPE_SIZE (TREE_TYPE (type)); else if (!(pushed = push_fields_onto_fieldstack
img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type))); (TREE_TYPE (field),
img_part->decl = NULL_TREE; fieldstack,
img_part->alias_set = -1; offset + bitpos_of_field (field),
img_part->base_for_components = false; has_union))
&& (DECL_SIZE (field)
count = 2; && !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
else if (TREE_CODE (type) == ARRAY_TYPE) nonzero, push the field onto the stack. */
{ push = true;
tree sz = TYPE_SIZE (type);
tree elsz = TYPE_SIZE (TREE_TYPE (type)); if (push)
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)
{ {
bool push = false; fieldoff_s *pair;
int pushed = 0;
pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
if (has_union pair->type = TREE_TYPE (field);
&& (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE pair->size = DECL_SIZE (field);
|| TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)) pair->decl = field;
*has_union = true; pair->offset = offset + bitpos_of_field (field);
count++;
if (!var_can_have_subvars (field)) }
push = true; else
else if (!(pushed = push_fields_onto_fieldstack count += pushed;
(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;
return count; return count;
} }
...@@ -4389,8 +4326,7 @@ create_variable_info_for (tree decl, const char *name) ...@@ -4389,8 +4326,7 @@ create_variable_info_for (tree decl, const char *name)
|| TREE_CODE (decltype) == QUAL_UNION_TYPE; || TREE_CODE (decltype) == QUAL_UNION_TYPE;
if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion) if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
{ {
push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion, push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion);
decltype);
if (hasunion) if (hasunion)
{ {
VEC_free (fieldoff_s, heap, fieldstack); VEC_free (fieldoff_s, heap, fieldstack);
...@@ -4398,7 +4334,6 @@ create_variable_info_for (tree decl, const char *name) ...@@ -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 /* If the variable doesn't have subvars, we may end up needing to
sort the field list and create fake variables for all the sort the field list and create fake variables for all the
fields. */ 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