From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27216 invoked by alias); 14 Nov 2007 14:07:34 -0000 Received: (qmail 26911 invoked by uid 22791); 14 Nov 2007 14:07:30 -0000 X-Spam-Check-By: sourceware.org Received: from ns2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 14 Nov 2007 14:07:23 +0000 Received: from Relay2.suse.de (mail2.suse.de [195.135.221.8]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mx2.suse.de (Postfix) with ESMTP id BE6D82BF65; Wed, 14 Nov 2007 15:07:19 +0100 (CET) Date: Wed, 14 Nov 2007 15:29:00 -0000 From: Richard Guenther To: gcc-patches@gcc.gnu.org Cc: Diego Novillo Subject: Re: Fix PR 33870 In-Reply-To: <84fc9c000711140510x2af9822dmbf085c51f9907cfd@mail.gmail.com> Message-ID: References: <4739C673.5080905@google.com> <84fc9c000711130808s5ecc11fcp1df00f20f379b76c@mail.gmail.com> <84fc9c000711140255m22880809w7611ad878918bf96@mail.gmail.com> <84fc9c000711140317o5abefc88n1c01e562d46baed0@mail.gmail.com> <473AE434.3060404@google.com> <84fc9c000711140435u2f885e90mca102b52b4860139@mail.gmail.com> <473AECED.3010804@google.com> <84fc9c000711140446l74fc9b36l4bfc2f024a21a66f@mail.gmail.com> <473AF069.7010101@google.com> <84fc9c000711140510x2af9822dmbf085c51f9907cfd@mail.gmail.com> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-11/txt/msg00800.txt.bz2 On Wed, 14 Nov 2007, Richard Guenther wrote: > On Nov 14, 2007 1:56 PM, Diego Novillo wrote: > > Richard Guenther wrote: > > > > > I guess in add_uids_for_ptset instead of > > > > > > ! if (SFT_NESTING_LEVEL (sft) > 0) > > > ! SFT_UNPARTITIONABLE_P (sft) = true; > > > > > > we can get away with only doing that if the type of the SFT itself could > > > have subvariables (which is probably again what you intended?). > > > > Hmm, well the SFTs themselves are usually of scalar type. The first SFT > > of an int[] array is of type int. Yes, the bug is around here. Perhaps > > the easiest way to fix this is to mark the variable earlier when we are > > pushing fields in the fieldstack (in the code that computes the nesting > > level). And then transport that marker into the SFT here. > > Yes, I'm doing that at the moment. Stay tuned for a patch. Like this one. It does a few things though: 1) Remove the nesting level stuff 2) Mark SFTs that can be used as a base for further sub-references (ARRAY_REFs, REAL/IMAGPART, COMPONENT_REF, etc.) 3) Mark all pointed-to SFTs that can be used as a base for sub-references as not partitionable 4) Fix a bug in TBAA pruning (without that we TBAA prune the pointed-to SFT (of type unsigned int) from the NMT as unsigned int does not alias with struct PgHdr *. We were wrongly using the pointer alias set instead of the pointed-to alias set for the pruning. This should reduce the compile-time regression we are seeing at the moment. Bootstrap and regtest on x86_64-unknown-linux-gnu in progress, I intend to commit this if that (as expected) finishes successfully. Richard. 2007-11-14 Richard Guenther * 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. Use the correct alias set to do TBAA pruning. (find_what_p_points_to): Only call set_uids_in_ptset for pointer variables. * 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. Index: tree.h =================================================================== *** tree.h (revision 130174) --- tree.h (working copy) *************** struct tree_memory_tag GTY(()) *** 2557,2562 **** --- 2557,2565 ---- /* True if this tag has global scope. */ unsigned int is_global : 1; + /* True if this tag can be a base for component accesses. */ + unsigned int base_for_components : 1; + /* True if this tag should not be grouped into a memory partition. */ unsigned int unpartitionable : 1; }; *************** struct tree_struct_field_tag GTY(()) *** 2579,2601 **** /* 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) /* Memory Partition Tags (MPTs) group memory symbols under one common name for the purposes of placing memory PHI nodes. */ --- 2582,2598 ---- /* Alias set for a DECL_NONADDRESSABLE_P field. Otherwise -1. */ alias_set_type alias_set; }; #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_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. */ Index: testsuite/gcc.dg/torture/pr33870.c =================================================================== *** testsuite/gcc.dg/torture/pr33870.c (revision 0) --- testsuite/gcc.dg/torture/pr33870.c (revision 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; + } + Index: tree-ssa-alias.c =================================================================== *** tree-ssa-alias.c (revision 130174) --- tree-ssa-alias.c (working copy) *************** get_or_create_used_part_for (size_t uid) *** 3791,3797 **** 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) { tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT"); --- 3791,3797 ---- static tree create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size, alias_set_type alias_set, ! bool base_for_components) { tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT"); *************** create_sft (tree var, tree field, unsign *** 3811,3817 **** SFT_OFFSET (subvar) = offset; SFT_SIZE (subvar) = size; SFT_ALIAS_SET (subvar) = alias_set; ! SFT_NESTING_LEVEL (subvar) = nesting_level; return subvar; } --- 3811,3818 ---- SFT_OFFSET (subvar) = offset; SFT_SIZE (subvar) = size; SFT_ALIAS_SET (subvar) = alias_set; ! SFT_BASE_FOR_COMPONENTS_P (subvar) = base_for_components; ! SFT_UNPARTITIONABLE_P (subvar) = false; return subvar; } *************** create_overlap_variables_for (tree var) *** 3833,3839 **** return; push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL, ! TREE_TYPE (var), 0); if (VEC_length (fieldoff_s, fieldstack) != 0) { subvar_t *subvars; --- 3834,3840 ---- return; push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL, ! TREE_TYPE (var)); if (VEC_length (fieldoff_s, fieldstack) != 0) { subvar_t *subvars; *************** create_overlap_variables_for (tree var) *** 3916,3921 **** --- 3917,3923 ---- 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) *************** create_overlap_variables_for (tree var) *** 3924,3932 **** && fosize == lastfosize && currfotype == lastfotype)) continue; ! ! subvar = create_sft (var, fo->type, fo->offset, fosize, ! fo->alias_set, fo->nesting_level); VEC_quick_push (tree, *subvars, subvar); if (dump_file) --- 3926,3933 ---- && fosize == lastfosize && currfotype == lastfotype)) continue; ! 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) *************** create_overlap_variables_for (tree var) *** 3937,3944 **** 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)); } lastfotype = currfotype; --- 3938,3944 ---- SFT_OFFSET (subvar)); fprintf (dump_file, " size " HOST_WIDE_INT_PRINT_DEC, SFT_SIZE (subvar)); ! fprintf (dump_file, "\n"); } lastfotype = currfotype; Index: tree-dfa.c =================================================================== *** tree-dfa.c (revision 130174) --- tree-dfa.c (working copy) *************** dump_subvars_for (FILE *file, tree var) *** 287,294 **** for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i) { print_generic_expr (file, subvar, dump_flags); fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar)); - fprintf (file, "[%u]", SFT_NESTING_LEVEL (subvar)); fprintf (file, " "); } --- 287,295 ---- for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i) { print_generic_expr (file, subvar, dump_flags); + if (SFT_BASE_FOR_COMPONENTS_P (subvar)) + fprintf (file, "@"); fprintf (file, "@" HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (subvar)); fprintf (file, " "); } *************** dump_variable (FILE *file, tree var) *** 424,430 **** { fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (var)); ! fprintf (file, ", nesting: %u", SFT_NESTING_LEVEL (var)); fprintf (file, ", partitionable: %s", SFT_UNPARTITIONABLE_P (var) ? "NO" : "YES"); } --- 425,432 ---- { fprintf (file, ", offset: " HOST_WIDE_INT_PRINT_UNSIGNED, SFT_OFFSET (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"); } Index: tree-flow.h =================================================================== *** tree-flow.h (revision 130174) --- tree-flow.h (working copy) *************** struct fieldoff *** 1159,1180 **** /* 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; }; 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); void sort_fieldstack (VEC(fieldoff_s,heap) *); void init_alias_heapvars (void); --- 1159,1179 ---- /* 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); Index: tree-ssa-structalias.c =================================================================== *** tree-ssa-structalias.c (revision 130174) --- tree-ssa-structalias.c (working copy) *************** sort_fieldstack (VEC(fieldoff_s,heap) *f *** 4053,4071 **** 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. */ 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 field; int count = 0; if (TREE_CODE (type) == COMPLEX_TYPE) { --- 4053,4068 ---- TYPE. ADDRESSABLE_TYPE is the type of the outermost object that could ! 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) { tree field; int count = 0; + int first_element = VEC_length (fieldoff_s, *fieldstack); if (TREE_CODE (type) == COMPLEX_TYPE) { *************** push_fields_onto_fieldstack (tree type, *** 4076,4081 **** --- 4073,4079 ---- 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); *************** push_fields_onto_fieldstack (tree type, *** 4083,4093 **** img_part->offset = offset + TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (type))); img_part->decl = NULL_TREE; img_part->alias_set = -1; ! return 2; } ! if (TREE_CODE (type) == ARRAY_TYPE) { tree sz = TYPE_SIZE (type); tree elsz = TYPE_SIZE (TREE_TYPE (type)); --- 4081,4092 ---- 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; ! count = 2; } ! else if (TREE_CODE (type) == ARRAY_TYPE) { tree sz = TYPE_SIZE (type); tree elsz = TYPE_SIZE (TREE_TYPE (type)); *************** push_fields_onto_fieldstack (tree type, *** 4125,4132 **** has_union, (TYPE_NONALIASED_COMPONENT (type) ? addressable_type ! : TREE_TYPE (type)), ! nesting_level + 1))) /* 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 */ --- 4124,4130 ---- 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_fields_onto_fieldstack (tree type, *** 4145,4160 **** pair->alias_set = get_alias_set (addressable_type); else pair->alias_set = -1; ! pair->nesting_level = nesting_level; count++; } else count += pushed; } - - return count; } for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL) { --- 4143,4158 ---- 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) { *************** push_fields_onto_fieldstack (tree type, *** 4175,4182 **** 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 --- 4173,4179 ---- 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 *************** push_fields_onto_fieldstack (tree type, *** 4197,4208 **** pair->alias_set = get_alias_set (addressable_type); else pair->alias_set = -1; ! pair->nesting_level = nesting_level; count++; } else count += pushed; } return count; } --- 4194,4211 ---- 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; } *************** create_variable_info_for (tree decl, con *** 4397,4403 **** if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion) { push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion, ! decltype, 0); if (hasunion) { VEC_free (fieldoff_s, heap, fieldstack); --- 4400,4406 ---- if (var_can_have_subvars (decl) && use_field_sensitive && !hasunion) { push_fields_onto_fieldstack (decltype, &fieldstack, 0, &hasunion, ! decltype); if (hasunion) { VEC_free (fieldoff_s, heap, fieldstack); *************** set_uids_in_ptset (tree ptr, bitmap into *** 4719,4725 **** { unsigned int i; bitmap_iterator bi; ! alias_set_type ptr_alias_set = get_alias_set (TREE_TYPE (ptr)); EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi) { --- 4722,4728 ---- { unsigned int i; bitmap_iterator bi; ! alias_set_type ptr_alias_set = get_alias_set (TREE_TYPE (TREE_TYPE (ptr))); EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi) { *************** set_uids_in_ptset (tree ptr, bitmap into *** 4762,4776 **** { 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 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) SFT_UNPARTITIONABLE_P (sft) = true; } } --- 4765,4779 ---- { bitmap_set_bit (into, DECL_UID (sft)); ! /* 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. 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; } } *************** find_what_p_points_to (tree p) *** 4996,5004 **** pi->pt_global_mem = 1; } ! set_uids_in_ptset (vi->decl, finished_solution, vi->solution, ! vi->directly_dereferenced, ! vi->no_tbaa_pruning); result = shared_bitmap_lookup (finished_solution); if (!result) --- 4999,5008 ---- pi->pt_global_mem = 1; } ! if (POINTER_TYPE_P (TREE_TYPE (vi->decl))) ! set_uids_in_ptset (vi->decl, finished_solution, vi->solution, ! vi->directly_dereferenced, ! vi->no_tbaa_pruning); result = shared_bitmap_lookup (finished_solution); if (!result) Index: tree-ssa-operands.c =================================================================== *** tree-ssa-operands.c (revision 130174) --- tree-ssa-operands.c (working copy) *************** access_can_touch_variable (tree ref, tre *** 1367,1399 **** 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. --- 1367,1374 ---- return true; } /* 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. *************** ref_nesting_level (tree full_ref) *** 1411,1422 **** 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. */ static bool ! add_vars_for_offset (tree full_ref, tree var, unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size, bool is_def) { bool added = false; --- 1386,1395 ---- 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. */ static bool ! add_vars_for_offset (tree var, unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size, bool is_def) { bool added = false; *************** add_vars_for_offset (tree full_ref, tree *** 1424,1478 **** 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); ! } /* Add all subvars of var that overlap with the access. Binary search for the first relevant SFT. */ --- 1397,1404 ---- subvar_t sv; unsigned int i; ! /* 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. */ *************** add_virtual_operand (tree var, stmt_ann_ *** 1575,1581 **** 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); else { --- 1501,1507 ---- 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 (al, offset, size, flags & opf_def); else {