aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-operands.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2007-11-16 14:40:04 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2007-11-16 14:40:04 +0000
commit99739a3e63eb906c77b8acdb76d4f40485eb56fe (patch)
treeb456fc38c0a138350839b7ebdcbf56a53752ed5d /gcc/tree-ssa-operands.c
parentbf3bde19e0bf954db21ec98ee179262ec68c5ded (diff)
downloadgcc-99739a3e63eb906c77b8acdb76d4f40485eb56fe.zip
gcc-99739a3e63eb906c77b8acdb76d4f40485eb56fe.tar.gz
gcc-99739a3e63eb906c77b8acdb76d4f40485eb56fe.tar.bz2
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
Diffstat (limited to 'gcc/tree-ssa-operands.c')
-rw-r--r--gcc/tree-ssa-operands.c112
1 files changed, 27 insertions, 85 deletions
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index cd8ade6..1f491ca 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -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