diff options
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/alias.c | 7 | ||||
-rw-r--r-- | gcc/tree-flow.h | 3 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.c | 13 | ||||
-rw-r--r-- | gcc/tree-ssa-structalias.c | 24 | ||||
-rw-r--r-- | gcc/tree.h | 5 |
6 files changed, 55 insertions, 10 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1b76b900021..95789e56955 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2007-06-20 Adam Nemet <anemet@caviumnetworks.com> + + 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 <hm.chang@apple.com> * config/i386/darwin.h (ASM_OUTPUT_COMMON): Print the size diff --git a/gcc/alias.c b/gcc/alias.c index c03ff03ce62..8064b8e087a 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 c23a094707a..0af3bdc3955 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 31911e68ef4..46c17ea68b1 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 663dff0b1cb..ddd7de3eb6c 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 ab6d5ff60f0..e6f1cee3c9f 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. */ |