diff options
author | Richard Guenther <rguenther@suse.de> | 2007-11-16 14:40:04 +0000 |
---|---|---|
committer | Richard Biener <rguenth@gcc.gnu.org> | 2007-11-16 14:40:04 +0000 |
commit | 99739a3e63eb906c77b8acdb76d4f40485eb56fe (patch) | |
tree | b456fc38c0a138350839b7ebdcbf56a53752ed5d /gcc/tree-ssa-operands.c | |
parent | bf3bde19e0bf954db21ec98ee179262ec68c5ded (diff) | |
download | gcc-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.c | 112 |
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 |