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
This commit is contained in:
parent
bf3bde19e0
commit
99739a3e63
@ -1,3 +1,29 @@
|
||||
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>
|
||||
|
||||
* config/spu/spu.md (floatunssidf2, floatunsdidf2): Inlined
|
||||
|
@ -1,3 +1,8 @@
|
||||
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>
|
||||
|
||||
PR fortran/33986
|
||||
|
30
gcc/testsuite/gcc.dg/torture/pr33870.c
Normal file
30
gcc/testsuite/gcc.dg/torture/pr33870.c
Normal file
@ -0,0 +1,30 @@
|
||||
/* { 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)
|
||||
{
|
||||
print_generic_expr (file, subvar, dump_flags);
|
||||
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, " ");
|
||||
}
|
||||
|
||||
@ -424,7 +425,8 @@ dump_variable (FILE *file, tree var)
|
||||
{
|
||||
fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED,
|
||||
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",
|
||||
SFT_UNPARTITIONABLE_P (var) ? "NO" : "YES");
|
||||
}
|
||||
|
@ -1159,22 +1159,21 @@ struct fieldoff
|
||||
/* Field. */
|
||||
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. */
|
||||
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, unsigned);
|
||||
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);
|
||||
|
@ -3791,7 +3791,7 @@ get_or_create_used_part_for (size_t uid)
|
||||
static tree
|
||||
create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
|
||||
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");
|
||||
|
||||
@ -3811,7 +3811,8 @@ create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset,
|
||||
SFT_OFFSET (subvar) = offset;
|
||||
SFT_SIZE (subvar) = size;
|
||||
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;
|
||||
}
|
||||
@ -3833,7 +3834,7 @@ create_overlap_variables_for (tree var)
|
||||
return;
|
||||
|
||||
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
|
||||
infos for. See tree-ssa-structalias.c:create_variable_info_for (). */
|
||||
if (VEC_length (fieldoff_s, fieldstack) != 0
|
||||
@ -3919,6 +3920,7 @@ create_overlap_variables_for (tree var)
|
||||
field, skip it. Note that we always need the field at
|
||||
offset 0 so we can properly handle pointers to the
|
||||
structure. */
|
||||
|
||||
if ((fo->offset != 0
|
||||
&& ((fo->offset <= up->minused
|
||||
&& fo->offset + fosize <= up->minused)
|
||||
@ -3927,9 +3929,8 @@ create_overlap_variables_for (tree var)
|
||||
&& fosize == lastfosize
|
||||
&& currfotype == lastfotype))
|
||||
continue;
|
||||
|
||||
subvar = create_sft (var, fo->type, fo->offset, fosize,
|
||||
fo->alias_set, fo->nesting_level);
|
||||
subvar = create_sft (var, fo->type, fo->offset,
|
||||
fosize, fo->alias_set, fo->base_for_components);
|
||||
VEC_quick_push (tree, *subvars, subvar);
|
||||
|
||||
if (dump_file)
|
||||
@ -3940,8 +3941,7 @@ create_overlap_variables_for (tree var)
|
||||
SFT_OFFSET (subvar));
|
||||
fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC,
|
||||
SFT_SIZE (subvar));
|
||||
fprintf (dump_file, " nesting level %d\n",
|
||||
SFT_NESTING_LEVEL (subvar));
|
||||
fprintf (dump_file, "\n");
|
||||
}
|
||||
|
||||
lastfotype = currfotype;
|
||||
|
@ -1367,36 +1367,10 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset,
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Given an aggregate expression FULL_REF, return the number of
|
||||
aggregates that are containing FULL_REF. So, given a structure
|
||||
reference a.b.c.d, the nesting level for this expression is 2 (the
|
||||
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.
|
||||
/* Add the actual variables accessed, given a member of a points-to set
|
||||
that is the SFT VAR, where the access is 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
|
||||
pointer to a structure, say
|
||||
@ -1411,12 +1385,10 @@ ref_nesting_level (tree full_ref)
|
||||
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
|
||||
to foop->a may be touching some single SFT if we have created some
|
||||
SFT's for a structure.
|
||||
|
||||
FULL_REF is the original memory expression being analyzed. */
|
||||
SFT's for a structure. */
|
||||
|
||||
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)
|
||||
{
|
||||
bool added = false;
|
||||
@ -1424,55 +1396,8 @@ add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset,
|
||||
subvar_t sv;
|
||||
unsigned int i;
|
||||
|
||||
if (full_ref
|
||||
&& SFT_NESTING_LEVEL (var) > 0
|
||||
&& 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);
|
||||
}
|
||||
/* Adjust offset by the pointed-to location. */
|
||||
offset += SFT_OFFSET (var);
|
||||
|
||||
/* Add all subvars of var that overlap with the access.
|
||||
Binary search for the first relevant SFT. */
|
||||
@ -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 (TREE_CODE (al) == STRUCT_FIELD_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
|
||||
{
|
||||
/* Call-clobbered tags may have non-call-clobbered
|
||||
|
@ -4053,19 +4053,16 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack)
|
||||
TYPE.
|
||||
|
||||
ADDRESSABLE_TYPE is the type of the outermost object that could
|
||||
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. */
|
||||
have its address taken. */
|
||||
|
||||
int
|
||||
push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
|
||||
HOST_WIDE_INT offset, bool *has_union,
|
||||
tree addressable_type, unsigned nesting_level)
|
||||
tree addressable_type)
|
||||
{
|
||||
tree field;
|
||||
int count = 0;
|
||||
int first_element = VEC_length (fieldoff_s, *fieldstack);
|
||||
|
||||
if (TREE_CODE (type) == COMPLEX_TYPE)
|
||||
{
|
||||
@ -4076,6 +4073,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
|
||||
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);
|
||||
@ -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->decl = NULL_TREE;
|
||||
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 elsz = TYPE_SIZE (TREE_TYPE (type));
|
||||
@ -4125,8 +4124,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
|
||||
has_union,
|
||||
(TYPE_NONALIASED_COMPONENT (type)
|
||||
? addressable_type
|
||||
: TREE_TYPE (type)),
|
||||
nesting_level + 1)))
|
||||
: 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 */
|
||||
@ -4145,64 +4143,69 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack,
|
||||
pair->alias_set = get_alias_set (addressable_type);
|
||||
else
|
||||
pair->alias_set = -1;
|
||||
pair->nesting_level = nesting_level;
|
||||
pair->base_for_components = false;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
count += pushed;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
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_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)
|
||||
else
|
||||
{
|
||||
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
|
||||
if (TREE_CODE (field) == FIELD_DECL)
|
||||
{
|
||||
fieldoff_s *pair;
|
||||
bool push = false;
|
||||
int pushed = 0;
|
||||
|
||||
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);
|
||||
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)))
|
||||
/* 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
|
||||
pair->alias_set = -1;
|
||||
pair->nesting_level = nesting_level;
|
||||
count++;
|
||||
}
|
||||
else
|
||||
count += pushed;
|
||||
}
|
||||
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;
|
||||
}
|
||||
@ -4397,7 +4400,7 @@ create_variable_info_for (tree decl, const char *name)
|
||||
if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion)
|
||||
{
|
||||
push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion,
|
||||
decltype, 0);
|
||||
decltype);
|
||||
if (hasunion)
|
||||
{
|
||||
VEC_free (fieldoff_s, heap, fieldstack);
|
||||
@ -4774,15 +4777,15 @@ set_uids_in_ptset (tree ptr, bitmap into, bitmap from, bool is_derefed,
|
||||
{
|
||||
bitmap_set_bit (into, DECL_UID (sft));
|
||||
|
||||
/* If SFT is inside a nested structure, it will
|
||||
be needed by the operand scanner to adjust
|
||||
offsets when adding operands to memory
|
||||
/* Pointed-to SFTs are needed by the operand scanner
|
||||
to adjust offsets when adding operands to memory
|
||||
expressions that dereference PTR. This means
|
||||
that memory partitioning may not partition
|
||||
this SFT because the operand scanner will not
|
||||
be able to find the other SFTs next to this
|
||||
one. */
|
||||
if (SFT_NESTING_LEVEL (sft) > 0)
|
||||
one. But we only need to do this if the pointed
|
||||
to type is aggregate. */
|
||||
if (SFT_BASE_FOR_COMPONENTS_P (sft))
|
||||
SFT_UNPARTITIONABLE_P (sft) = true;
|
||||
}
|
||||
}
|
||||
|
14
gcc/tree.h
14
gcc/tree.h
@ -2557,6 +2557,10 @@ struct tree_memory_tag GTY(())
|
||||
/* True if this tag has global scope. */
|
||||
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. */
|
||||
unsigned int unpartitionable : 1;
|
||||
};
|
||||
@ -2579,23 +2583,17 @@ struct tree_struct_field_tag GTY(())
|
||||
|
||||
/* Alias set for a DECL_NONADDRESSABLE_P field. Otherwise -1. */
|
||||
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_OFFSET(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.offset)
|
||||
#define SFT_SIZE(NODE) (STRUCT_FIELD_TAG_CHECK (NODE)->sft.size)
|
||||
#define SFT_NONADDRESSABLE_P(NODE) \
|
||||
(STRUCT_FIELD_TAG_CHECK (NODE)->sft.alias_set != -1)
|
||||
#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) \
|
||||
(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
|
||||
common name for the purposes of placing memory PHI nodes. */
|
||||
|
Loading…
Reference in New Issue
Block a user