Commit 99739a3e by Richard Guenther Committed by Richard Biener

re PR tree-optimization/33870 (miscompiles sqlite)

2007-11-16  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/33870
	* tree.h (struct tree_memory_tag): Add base_for_components flag.
	(struct tree_struct_field_tag): Remove nesting_level field.
	(SFT_NESTING_LEVEL): Remove.
	(SFT_BASE_FOR_COMPONENTS_P): Add.
	* tree-flow.h (struct fieldoff): Remove nesting_level field.  Add
	base_for_components flag.
	(push_fields_onto_fieldstack): Remove nesting_level parameter.
	* tree-ssa-alias.c (create_sft): Likewise.  Add base_for_components
	parameter.
	(create_overlap_variables_for): Deal with it.
	* tree-dfa.c (dump_subvars_for): Likewise.
	(dump_variable): Likewise.
	* tree-ssa-structalias.c (push_fields_onto_fieldstack): Likewise.
	Set base_for_components for first elements of sub-structures.
	(create_variable_info_for): Handle base_for_components.
	(set_uids_in_ptset): Always set SFT_UNPARTITIONABLE_P for
	pointed-to SFTs if SFT_BASE_FOR_COMPONENTS_P is set.
	* tree-ssa-operands.c (ref_nesting_level): Remove.
	(add_vars_for_offset): Remove full_ref parameter, always add
	the offset of the pointed-to SFT.
	(add_virtual_operand): Adjust for changed signature of
	add_vars_for_offset.

	* gcc.dg/torture/pr33870.c: New testcase.

From-SVN: r130231
parent bf3bde19
2007-11-16 Richard Guenther <rguenther@suse.de>
PR tree-optimization/33870
* tree.h (struct tree_memory_tag): Add base_for_components flag.
(struct tree_struct_field_tag): Remove nesting_level field.
(SFT_NESTING_LEVEL): Remove.
(SFT_BASE_FOR_COMPONENTS_P): Add.
* tree-flow.h (struct fieldoff): Remove nesting_level field. Add
base_for_components flag.
(push_fields_onto_fieldstack): Remove nesting_level parameter.
* tree-ssa-alias.c (create_sft): Likewise. Add base_for_components
parameter.
(create_overlap_variables_for): Deal with it.
* tree-dfa.c (dump_subvars_for): Likewise.
(dump_variable): Likewise.
* tree-ssa-structalias.c (push_fields_onto_fieldstack): Likewise.
Set base_for_components for first elements of sub-structures.
(create_variable_info_for): Handle base_for_components.
(set_uids_in_ptset): Always set SFT_UNPARTITIONABLE_P for
pointed-to SFTs if SFT_BASE_FOR_COMPONENTS_P is set.
* tree-ssa-operands.c (ref_nesting_level): Remove.
(add_vars_for_offset): Remove full_ref parameter, always add
the offset of the pointed-to SFT.
(add_virtual_operand): Adjust for changed signature of
add_vars_for_offset.
2007-11-16 Sa Liu <saliu@de.ibm.com> 2007-11-16 Sa Liu <saliu@de.ibm.com>
* config/spu/spu.md (floatunssidf2, floatunsdidf2): Inlined * config/spu/spu.md (floatunssidf2, floatunsdidf2): Inlined
2007-11-16 Richard Guenther <rguenther@suse.de>
PR tree-optimization/33870
* gcc.dg/torture/pr33870.c: New testcase.
2007-11-16 Paul Thomas <pault@gcc.gnu.org> 2007-11-16 Paul Thomas <pault@gcc.gnu.org>
PR fortran/33986 PR fortran/33986
/* { dg-do run } */
/* { dg-options "--param max-aliased-vops=1" } */
struct X {
int i;
int a[4];
} m;
int a[4];
int __attribute__((noinline)) foo(int b)
{
int (*p)[4] = b ? &a : &m.a;
a[3] = 0;
(*p)[3] = 1;
return (*p)[3] + (*p)[2] + (*p)[1] + a[0] + a[3];
}
extern void abort (void);
int main()
{
int i;
for (i = 0; i < 4; ++i)
a[i] = 0;
if (foo(1) != 2)
abort ();
return 0;
}
...@@ -288,7 +288,8 @@ dump_subvars_for (FILE *file, tree var) ...@@ -288,7 +288,8 @@ dump_subvars_for (FILE *file, tree var)
{ {
print_generic_expr (file, subvar, dump_flags); print_generic_expr (file, subvar, dump_flags);
fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar)); fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar));
fprintf (file, "[%u]", SFT_NESTING_LEVEL (subvar)); if (SFT_BASE_FOR_COMPONENTS_P (subvar))
fprintf (file, "[B]");
fprintf (file, " "); fprintf (file, " ");
} }
...@@ -424,7 +425,8 @@ dump_variable (FILE *file, tree var) ...@@ -424,7 +425,8 @@ dump_variable (FILE *file, tree var)
{ {
fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED, fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED,
SFT_OFFSET (var)); SFT_OFFSET (var));
fprintf (file, ", nesting: %u", SFT_NESTING_LEVEL (var)); fprintf (file, ", base for components: %s",
SFT_BASE_FOR_COMPONENTS_P (var) ? "NO" : "YES");
fprintf (file, ", partitionable: %s", fprintf (file, ", partitionable: %s",
SFT_UNPARTITIONABLE_P (var) ? "NO" : "YES"); SFT_UNPARTITIONABLE_P (var) ? "NO" : "YES");
} }
......
...@@ -1159,22 +1159,21 @@ struct fieldoff ...@@ -1159,22 +1159,21 @@ struct fieldoff
/* Field. */ /* Field. */
tree decl; tree decl;
/* Nesting level. This number represents how many structures are
wrapping this field. */
unsigned nesting_level;
/* Offset from the base of the base containing object to this field. */ /* Offset from the base of the base containing object to this field. */
HOST_WIDE_INT offset; HOST_WIDE_INT offset;
/* Alias set for the field. */ /* Alias set for the field. */
alias_set_type alias_set; 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; typedef struct fieldoff fieldoff_s;
DEF_VEC_O(fieldoff_s); DEF_VEC_O(fieldoff_s);
DEF_VEC_ALLOC_O(fieldoff_s,heap); DEF_VEC_ALLOC_O(fieldoff_s,heap);
int push_fields_onto_fieldstack (tree, VEC(fieldoff_s,heap) **, HOST_WIDE_INT, int push_fields_onto_fieldstack (tree, VEC(fieldoff_s,heap) **,
bool *, tree, unsigned); HOST_WIDE_INT, bool *, tree);
void sort_fieldstack (VEC(fieldoff_s,heap) *); void sort_fieldstack (VEC(fieldoff_s,heap) *);
void init_alias_heapvars (void); void init_alias_heapvars (void);
......
...@@ -3791,7 +3791,7 @@ get_or_create_used_part_for (size_t uid) ...@@ -3791,7 +3791,7 @@ get_or_create_used_part_for (size_t uid)
static tree static tree
create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset, create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT size, alias_set_type alias_set, unsigned HOST_WIDE_INT size, alias_set_type alias_set,
unsigned nesting_level) bool base_for_components)
{ {
tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT"); tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT");
...@@ -3811,7 +3811,8 @@ create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset, ...@@ -3811,7 +3811,8 @@ create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
SFT_OFFSET (subvar) = offset; SFT_OFFSET (subvar) = offset;
SFT_SIZE (subvar) = size; SFT_SIZE (subvar) = size;
SFT_ALIAS_SET (subvar) = alias_set; SFT_ALIAS_SET (subvar) = alias_set;
SFT_NESTING_LEVEL (subvar) = nesting_level; SFT_BASE_FOR_COMPONENTS_P (subvar) = base_for_components;
SFT_UNPARTITIONABLE_P (subvar) = false;
return subvar; return subvar;
} }
...@@ -3833,7 +3834,7 @@ create_overlap_variables_for (tree var) ...@@ -3833,7 +3834,7 @@ create_overlap_variables_for (tree var)
return; return;
push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL, push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL,
TREE_TYPE (var), 0); TREE_TYPE (var));
/* Make sure to not create SFTs for structs we won't generate variable /* Make sure to not create SFTs for structs we won't generate variable
infos for. See tree-ssa-structalias.c:create_variable_info_for (). */ infos for. See tree-ssa-structalias.c:create_variable_info_for (). */
if (VEC_length (fieldoff_s, fieldstack) != 0 if (VEC_length (fieldoff_s, fieldstack) != 0
...@@ -3919,6 +3920,7 @@ create_overlap_variables_for (tree var) ...@@ -3919,6 +3920,7 @@ create_overlap_variables_for (tree var)
field, skip it. Note that we always need the field at field, skip it. Note that we always need the field at
offset 0 so we can properly handle pointers to the offset 0 so we can properly handle pointers to the
structure. */ structure. */
if ((fo->offset != 0 if ((fo->offset != 0
&& ((fo->offset <= up->minused && ((fo->offset <= up->minused
&& fo->offset + fosize <= up->minused) && fo->offset + fosize <= up->minused)
...@@ -3927,9 +3929,8 @@ create_overlap_variables_for (tree var) ...@@ -3927,9 +3929,8 @@ create_overlap_variables_for (tree var)
&& fosize == lastfosize && fosize == lastfosize
&& currfotype == lastfotype)) && currfotype == lastfotype))
continue; continue;
subvar = create_sft (var, fo->type, fo->offset,
subvar = create_sft (var, fo->type, fo->offset, fosize, fosize, fo->alias_set, fo->base_for_components);
fo->alias_set, fo->nesting_level);
VEC_quick_push (tree, *subvars, subvar); VEC_quick_push (tree, *subvars, subvar);
if (dump_file) if (dump_file)
...@@ -3940,8 +3941,7 @@ create_overlap_variables_for (tree var) ...@@ -3940,8 +3941,7 @@ create_overlap_variables_for (tree var)
SFT_OFFSET (subvar)); SFT_OFFSET (subvar));
fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC, fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
SFT_SIZE (subvar)); SFT_SIZE (subvar));
fprintf (dump_file, " nesting level %d\n", fprintf (dump_file, "\n");
SFT_NESTING_LEVEL (subvar));
} }
lastfotype = currfotype; lastfotype = currfotype;
......
...@@ -1367,36 +1367,10 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset, ...@@ -1367,36 +1367,10 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
return true; return true;
} }
/* Add the actual variables accessed, given a member of a points-to set
/* Given an aggregate expression FULL_REF, return the number of that is the SFT VAR, where the access is of SIZE at OFFSET from VAR.
aggregates that are containing FULL_REF. So, given a structure IS_CALL_SITE is true if this is a call, and IS_DEF is true if this is
reference a.b.c.d, the nesting level for this expression is 2 (the supposed to be a vdef, and false if this should be a VUSE.
number of '.' in the expression minus 1). */
static unsigned
ref_nesting_level (tree full_ref)
{
unsigned nesting_level = 0;
if (!handled_component_p (full_ref))
return 0;
full_ref = TREE_OPERAND (full_ref, 0);
while (handled_component_p (full_ref))
{
nesting_level++;
full_ref = TREE_OPERAND (full_ref, 0);
}
return nesting_level;
}
/* Add the actual variables FULL_REF can access, given a member of
FULL_REF's points-to set VAR, where FULL_REF is an access of SIZE at
OFFSET from var. IS_CALL_SITE is true if this is a call, and IS_DEF
is true if this is supposed to be a vdef, and false if this should
be a VUSE.
The real purpose of this function is to take a points-to set for a The real purpose of this function is to take a points-to set for a
pointer to a structure, say pointer to a structure, say
...@@ -1411,12 +1385,10 @@ ref_nesting_level (tree full_ref) ...@@ -1411,12 +1385,10 @@ ref_nesting_level (tree full_ref)
This is necessary because foop only actually points to foo's first This is necessary because foop only actually points to foo's first
member, so that is all the points-to set contains. However, an access member, so that is all the points-to set contains. However, an access
to foop->a may be touching some single SFT if we have created some to foop->a may be touching some single SFT if we have created some
SFT's for a structure. SFT's for a structure. */
FULL_REF is the original memory expression being analyzed. */
static bool static bool
add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset, add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset,
unsigned HOST_WIDE_INT size, bool is_def) unsigned HOST_WIDE_INT size, bool is_def)
{ {
bool added = false; bool added = false;
...@@ -1424,55 +1396,8 @@ add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset, ...@@ -1424,55 +1396,8 @@ add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset,
subvar_t sv; subvar_t sv;
unsigned int i; unsigned int i;
if (full_ref /* Adjust offset by the pointed-to location. */
&& SFT_NESTING_LEVEL (var) > 0 offset += SFT_OFFSET (var);
&& ref_nesting_level (full_ref) < SFT_NESTING_LEVEL (var))
{
/* Since VAR is an SFT inside a nested structure, the OFFSET
computed by get_ref_base_and_extent is the offset from the
start of the immediately containing structure. If VAR is an
SFT inside a nested structure, then FULL_REF may be a
reference to the structure immediately enclosing SFT, and so
OFFSET will be the offset from the start of the immediately
enclosing structure.
However, to find out what other SFTs are affected by this
reference, we need to know the offsets starting at the root
structure in the nesting hierarchy.
For instance, given the following structure:
struct X {
int a;
struct Y {
int b;
struct Z {
int c[3];
} d;
} e;
} m;
and the following address expression:
p_1 = &m.e.d;
This structure will receive 5 SFTs, namely 2 for fields 'a'
and 'b' and 3 for the array 'c' in struct Z. So, the
reference p_1->c[2] and m.e.d.c[2] access the exact same
memory location (ie, SFT.5).
Now, alias analysis computed the points-to set for pointer
p_1 as { SFT.3 } because that is the first field that p_1
actually points to. When the expression p_1->c[2] is
analyzed, get_ref_base_and_extent will return an offset of 96
because we are accessing the third element of the array. But
the SFT we are looking for is actually at offset 160,
counting from the top of struct X.
Therefore, we adjust OFFSET by the offset of VAR so that we
can get at all the fields starting at VAR. */
offset += SFT_OFFSET (var);
}
/* Add all subvars of var that overlap with the access. /* Add all subvars of var that overlap with the access.
Binary search for the first relevant SFT. */ Binary search for the first relevant SFT. */
...@@ -1575,8 +1500,25 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags, ...@@ -1575,8 +1500,25 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags,
if it is a potential points-to location. */ if it is a potential points-to location. */
if (TREE_CODE (al) == STRUCT_FIELD_TAG if (TREE_CODE (al) == STRUCT_FIELD_TAG
&& TREE_CODE (var) == NAME_MEMORY_TAG) && TREE_CODE (var) == NAME_MEMORY_TAG)
none_added &= !add_vars_for_offset (full_ref, al, offset, size, {
flags & opf_def); if (SFT_BASE_FOR_COMPONENTS_P (al))
{
/* If AL is the first SFT of a component, it can be used
to find other SFTs at [offset, size] adjacent to it. */
none_added &= !add_vars_for_offset (al, offset, size,
flags & opf_def);
}
else if ((unsigned HOST_WIDE_INT)offset < SFT_SIZE (al))
{
/* Otherwise, we only need to consider it if
[offset, size] overlaps with AL. */
if (flags & opf_def)
append_vdef (al);
else
append_vuse (al);
none_added = false;
}
}
else else
{ {
/* Call-clobbered tags may have non-call-clobbered /* Call-clobbered tags may have non-call-clobbered
......
...@@ -4053,19 +4053,16 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack) ...@@ -4053,19 +4053,16 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
TYPE. TYPE.
ADDRESSABLE_TYPE is the type of the outermost object that could ADDRESSABLE_TYPE is the type of the outermost object that could
have its address taken. have its address taken. */
NESTING_LEVEL indicates whether TYPE is a structure nested inside
another, it starts at 0 and it is incremented by one on every
structure recursed into. */
int 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, unsigned nesting_level) tree addressable_type)
{ {
tree field; tree field;
int count = 0; int count = 0;
int first_element = VEC_length (fieldoff_s, *fieldstack);
if (TREE_CODE (type) == COMPLEX_TYPE) if (TREE_CODE (type) == COMPLEX_TYPE)
{ {
...@@ -4076,6 +4073,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, ...@@ -4076,6 +4073,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
real_part->offset = offset; real_part->offset = offset;
real_part->decl = NULL_TREE; real_part->decl = NULL_TREE;
real_part->alias_set = -1; real_part->alias_set = -1;
real_part->base_for_components = false;
img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL); img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
img_part->type = TREE_TYPE (type); img_part->type = TREE_TYPE (type);
...@@ -4083,11 +4081,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, ...@@ -4083,11 +4081,12 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
img_part->offset = offset + TREE_INT_CST_LOW (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->decl = NULL_TREE;
img_part->alias_set = -1; img_part->alias_set = -1;
img_part->base_for_components = false;
return 2; count = 2;
} }
if (TREE_CODE (type) == ARRAY_TYPE) else if (TREE_CODE (type) == ARRAY_TYPE)
{ {
tree sz = TYPE_SIZE (type); tree sz = TYPE_SIZE (type);
tree elsz = TYPE_SIZE (TREE_TYPE (type)); tree elsz = TYPE_SIZE (TREE_TYPE (type));
...@@ -4125,8 +4124,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, ...@@ -4125,8 +4124,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
has_union, has_union,
(TYPE_NONALIASED_COMPONENT (type) (TYPE_NONALIASED_COMPONENT (type)
? addressable_type ? addressable_type
: TREE_TYPE (type)), : TREE_TYPE (type)))))
nesting_level + 1)))
/* Empty structures may have actual size, like in C++. So /* Empty structures may have actual size, like in C++. So
see if we didn't push any subfields and the size is see if we didn't push any subfields and the size is
nonzero, push the field onto the stack */ nonzero, push the field onto the stack */
...@@ -4145,64 +4143,69 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, ...@@ -4145,64 +4143,69 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
pair->alias_set = get_alias_set (addressable_type); pair->alias_set = get_alias_set (addressable_type);
else else
pair->alias_set = -1; pair->alias_set = -1;
pair->nesting_level = nesting_level; pair->base_for_components = false;
count++; count++;
} }
else else
count += pushed; count += pushed;
} }
return count;
} }
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) else
if (TREE_CODE (field) == FIELD_DECL) {
{ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
bool push = false; if (TREE_CODE (field) == FIELD_DECL)
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)),
nesting_level + 1))
&& 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)
{ {
fieldoff_s *pair; bool push = false;
int pushed = 0;
pair = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL);
pair->type = TREE_TYPE (field); if (has_union
pair->size = DECL_SIZE (field); && (TREE_CODE (TREE_TYPE (field)) == QUAL_UNION_TYPE
pair->decl = field; || TREE_CODE (TREE_TYPE (field)) == UNION_TYPE))
pair->offset = offset + bitpos_of_field (field); *has_union = true;
if (DECL_NONADDRESSABLE_P (field))
pair->alias_set = get_alias_set (addressable_type); 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)))
/* 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 (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 else
pair->alias_set = -1; count += pushed;
pair->nesting_level = nesting_level; }
count++; }
}
else /* Make sure the first pushed field is marked as eligible for
count += pushed; being a base for component references. */
} if (count > 0)
VEC_index (fieldoff_s, *fieldstack, first_element)->base_for_components = true;
return count; return count;
} }
...@@ -4397,7 +4400,7 @@ create_variable_info_for (tree decl, const char *name) ...@@ -4397,7 +4400,7 @@ create_variable_info_for (tree decl, const char *name)
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, 0); decltype);
if (hasunion) if (hasunion)
{ {
VEC_free (fieldoff_s, heap, fieldstack); VEC_free (fieldoff_s, heap, fieldstack);
...@@ -4774,15 +4777,15 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed, ...@@ -4774,15 +4777,15 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
{ {
bitmap_set_bit (into, DECL_UID (sft)); bitmap_set_bit (into, DECL_UID (sft));
/* If SFT is inside a nested structure, it will /* Pointed-to SFTs are needed by the operand scanner
be needed by the operand scanner to adjust to adjust offsets when adding operands to memory
offsets when adding operands to memory
expressions that dereference PTR. This means expressions that dereference PTR. This means
that memory partitioning may not partition that memory partitioning may not partition
this SFT because the operand scanner will not this SFT because the operand scanner will not
be able to find the other SFTs next to this be able to find the other SFTs next to this
one. */ one. But we only need to do this if the pointed
if (SFT_NESTING_LEVEL (sft) > 0) to type is aggregate. */
if (SFT_BASE_FOR_COMPONENTS_P (sft))
SFT_UNPARTITIONABLE_P (sft) = true; SFT_UNPARTITIONABLE_P (sft) = true;
} }
} }
......
...@@ -2557,6 +2557,10 @@ struct tree_memory_tag GTY(()) ...@@ -2557,6 +2557,10 @@ struct tree_memory_tag GTY(())
/* True if this tag has global scope. */ /* True if this tag has global scope. */
unsigned int is_global : 1; unsigned int is_global : 1;
/* True if this tag is the first field of an aggregate type that
can be used to find adjacent SFTs belonging to the same aggregate. */
unsigned int base_for_components : 1;
/* True if this tag should not be grouped into a memory partition. */ /* True if this tag should not be grouped into a memory partition. */
unsigned int unpartitionable : 1; unsigned int unpartitionable : 1;
}; };
...@@ -2579,23 +2583,17 @@ struct tree_struct_field_tag GTY(()) ...@@ -2579,23 +2583,17 @@ struct tree_struct_field_tag GTY(())
/* Alias set for a DECL_NONADDRESSABLE_P field. Otherwise -1. */ /* Alias set for a DECL_NONADDRESSABLE_P field. Otherwise -1. */
alias_set_type alias_set; alias_set_type alias_set;
/* Nesting level for this subvariable. This indicates how many
structures are wrapping this field. Fields at the top level have
a nesting level of 0. */
unsigned int nesting_level;
}; };
#define SFT_PARENT_VAR(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.parent_var) #define SFT_PARENT_VAR(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.parent_var)
#define SFT_OFFSET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.offset) #define SFT_OFFSET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.offset)
#define SFT_SIZE(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.size) #define SFT_SIZE(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.size)
#define SFT_NONADDRESSABLE_P(NODE) \ #define SFT_NONADDRESSABLE_P(NODE) \
(STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set != -1) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set != -1)
#define SFT_ALIAS_SET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set) #define SFT_ALIAS_SET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set)
#define SFT_NESTING_LEVEL(NODE) \
(STRUCT_FIELD_TAG_CHECK (NODE)->sft.nesting_level)
#define SFT_UNPARTITIONABLE_P(NODE) \ #define SFT_UNPARTITIONABLE_P(NODE) \
(STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.unpartitionable) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.unpartitionable)
#define SFT_BASE_FOR_COMPONENTS_P(NODE) \
(STRUCT_FIELD_TAG_CHECK (NODE)->sft.common.base_for_components)
/* Memory Partition Tags (MPTs) group memory symbols under one /* Memory Partition Tags (MPTs) group memory symbols under one
common name for the purposes of placing memory PHI nodes. */ common name for the purposes of placing memory PHI nodes. */
......
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