From: Adam Nemet Date: Wed, 20 Jun 2007 18:19:10 +0000 (+0000) Subject: re PR tree-optimization/25737 (ACATS c974001 c974013 hang with struct aliasing) X-Git-Tag: releases/gcc-4.3.0~4364 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3d9b47dc431c0e8b967f390f28a68fe371d47eb4;p=thirdparty%2Fgcc.git re PR tree-optimization/25737 (ACATS c974001 c974013 hang with struct aliasing) PR tree-optimization/25737 * tree.h (struct tree_struct_field_tag): Add new field alias_set. (SFT_NONADDRESSABLE_P, SFT_ALIAS_SET): New macros. * tree-flow.h (struct fieldoff): Add new field alias_set. * tree-ssa-structalias.c (push_fields_onto_fieldstack): Add new argument addressable_type. Set alias_set of fieldoff. * tree-ssa-alias.c (create_sft): Add new argument alias_set. (create_overlap_variables_for): Pass alias_set from fieldoff to create_sft. * alias.c (get_alias_set): Use alias_set from SFT if set. From-SVN: r125890 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b76b9000219..95789e56955d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2007-06-20 Adam Nemet + + PR tree-optimization/25737 + * tree.h (struct tree_struct_field_tag): Add new field alias_set. + (SFT_NONADDRESSABLE_P, SFT_ALIAS_SET): New macros. + * tree-flow.h (struct fieldoff): Add new field alias_set. + * tree-ssa-structalias.c (push_fields_onto_fieldstack): Add new + argument addressable_type. Set alias_set of fieldoff. + * tree-ssa-alias.c (create_sft): Add new argument alias_set. + (create_overlap_variables_for): Pass alias_set from fieldoff to + create_sft. + * alias.c (get_alias_set): Use alias_set from SFT if set. + 2007-06-20 Hui-May Chang * config/i386/darwin.h (ASM_OUTPUT_COMMON): Print the size diff --git a/gcc/alias.c b/gcc/alias.c index c03ff03ce620..8064b8e087a4 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -586,6 +586,13 @@ get_alias_set (tree t) return 0; } + /* For non-addressable fields we return the alias set of the + outermost object that could have its address taken. If this + is an SFT use the precomputed value. */ + if (TREE_CODE (t) == STRUCT_FIELD_TAG + && SFT_NONADDRESSABLE_P (t)) + return SFT_ALIAS_SET (t); + /* Otherwise, pick up the outermost object that we could have a pointer to, processing conversions as above. */ while (component_uses_parent_alias_set (t)) diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index c23a094707a2..0af3bdc39559 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -1158,13 +1158,14 @@ struct fieldoff tree size; tree decl; HOST_WIDE_INT offset; + HOST_WIDE_INT 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 *); + HOST_WIDE_INT, bool *, tree); void sort_fieldstack (VEC(fieldoff_s,heap) *); void init_alias_heapvars (void); diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c index 31911e68ef4f..46c17ea68b17 100644 --- a/gcc/tree-ssa-alias.c +++ b/gcc/tree-ssa-alias.c @@ -3646,11 +3646,13 @@ get_or_create_used_part_for (size_t uid) /* Create and return a structure sub-variable for field type FIELD at - offset OFFSET, with size SIZE, of variable VAR. */ + offset OFFSET, with size SIZE, of variable VAR. If ALIAS_SET not + -1 this field is non-addressable and we should use this alias set + with this field. */ static tree create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset, - unsigned HOST_WIDE_INT size) + unsigned HOST_WIDE_INT size, HOST_WIDE_INT alias_set) { tree subvar = create_tag_raw (STRUCT_FIELD_TAG, field, "SFT"); @@ -3669,6 +3671,7 @@ create_sft (tree var, tree field, unsigned HOST_WIDE_INT offset, SFT_PARENT_VAR (subvar) = var; SFT_OFFSET (subvar) = offset; SFT_SIZE (subvar) = size; + SFT_ALIAS_SET (subvar) = alias_set; return subvar; } @@ -3688,7 +3691,8 @@ create_overlap_variables_for (tree var) || up->write_only) return; - push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL); + push_fields_onto_fieldstack (TREE_TYPE (var), &fieldstack, 0, NULL, + TREE_TYPE (var)); if (VEC_length (fieldoff_s, fieldstack) != 0) { subvar_t *subvars; @@ -3780,7 +3784,8 @@ create_overlap_variables_for (tree var) continue; sv = GGC_NEW (struct subvar); sv->next = *subvars; - sv->var = create_sft (var, fo->type, fo->offset, fosize); + sv->var = + create_sft (var, fo->type, fo->offset, fosize, fo->alias_set); if (dump_file) { diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c index 663dff0b1cbe..ddd7de3eb6c0 100644 --- a/gcc/tree-ssa-structalias.c +++ b/gcc/tree-ssa-structalias.c @@ -3695,11 +3695,13 @@ sort_fieldstack (VEC(fieldoff_s,heap) *fieldstack) than just the immediately containing structure. Returns the number of fields pushed. HAS_UNION is set to true if we find a union type as a field of - TYPE. */ + 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) + HOST_WIDE_INT offset, bool *has_union, + tree addressable_type) { tree field; int count = 0; @@ -3712,12 +3714,14 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, real_part->size = TYPE_SIZE (TREE_TYPE (type)); real_part->offset = offset; real_part->decl = NULL_TREE; + real_part->alias_set = -1; img_part = VEC_safe_push (fieldoff_s, heap, *fieldstack, NULL); img_part->type = TREE_TYPE (type); img_part->size = 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->alias_set = -1; return 2; } @@ -3755,7 +3759,8 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, push = true; else if (!(pushed = push_fields_onto_fieldstack (TREE_TYPE (type), fieldstack, - offset + i * TREE_INT_CST_LOW (elsz), has_union))) + offset + i * TREE_INT_CST_LOW (elsz), has_union, + 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 */ @@ -3770,6 +3775,7 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, pair->size = elsz; pair->decl = NULL_TREE; pair->offset = offset + i * TREE_INT_CST_LOW (elsz); + pair->alias_set = -1; count++; } else @@ -3794,7 +3800,10 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, push = true; else if (!(pushed = push_fields_onto_fieldstack (TREE_TYPE (field), fieldstack, - offset + bitpos_of_field (field), has_union)) + 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 @@ -3811,6 +3820,10 @@ push_fields_onto_fieldstack (tree type, VEC(fieldoff_s,heap) **fieldstack, 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; count++; } else @@ -4009,7 +4022,8 @@ create_variable_info_for (tree decl, const char *name) || TREE_CODE (decltype) == QUAL_UNION_TYPE; 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); if (hasunion) { VEC_free (fieldoff_s, heap, fieldstack); diff --git a/gcc/tree.h b/gcc/tree.h index ab6d5ff60f08..e6f1cee3c9fc 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2516,10 +2516,15 @@ struct tree_struct_field_tag GTY(()) /* Size of the field. */ unsigned HOST_WIDE_INT size; + /* Alias set for a DECL_NONADDRESSABLE_P field. Otherwise -1. */ + HOST_WIDE_INT 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) /* Memory Partition Tags (MPTs) group memory symbols under one common name for the purposes of placing memory PHI nodes. */