diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-10-29 18:27:38 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-10-29 18:27:38 +0000 |
commit | 8c5a45b9d761e701286ffc479a0a018cc96d890a (patch) | |
tree | c1b0567e0bc3a2faf2e843ff14afa359047427ee /gcc | |
parent | 0a39bce0303b563f5745b32c67aa925509b67226 (diff) | |
download | gcc-8c5a45b9d761e701286ffc479a0a018cc96d890a.tar.gz |
2007-10-29 Richard Guenther <rguenther@suse.de>
* tree-flow-inline.h (get_subvar_at): Use binary search.
(get_first_overlapping_subvar): New function to binary search
for the first overlapping subvar.
* tree-ssa-operands.c (add_vars_for_offset): Strip down to
just handle adding subvars for a pointed-to subvar. Optimize
and use get_first_overlapping_subvar.
(add_vars_for_bitmap): Fold into single caller.
(add_virtual_operand): Streamline, inherit add_vars_for_bitmap
and non pointed-to bits of add_vars_for_offset.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@129727 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/tree-flow-inline.h | 79 | ||||
-rw-r--r-- | gcc/tree-ssa-operands.c | 131 |
3 files changed, 150 insertions, 72 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 315649734ee..f452aeaf37a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2007-10-29 Richard Guenther <rguenther@suse.de> + + * tree-flow-inline.h (get_subvar_at): Use binary search. + (get_first_overlapping_subvar): New function to binary search + for the first overlapping subvar. + * tree-ssa-operands.c (add_vars_for_offset): Strip down to + just handle adding subvars for a pointed-to subvar. Optimize + and use get_first_overlapping_subvar. + (add_vars_for_bitmap): Fold into single caller. + (add_virtual_operand): Streamline, inherit add_vars_for_bitmap + and non pointed-to bits of add_vars_for_offset. + 2007-10-29 Revital Eres <eres@il.ibm.com> * modulo-sched.c (sms_schedule): Add DF_UD_CHAIN problem. diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h index b87f3d2fc84..4669588558e 100644 --- a/gcc/tree-flow-inline.h +++ b/gcc/tree-flow-inline.h @@ -1610,17 +1610,88 @@ static inline tree get_subvar_at (tree var, unsigned HOST_WIDE_INT offset) { subvar_t sv = get_subvars_for_var (var); - unsigned int i; + int low, high; + + low = 0; + high = VEC_length (tree, sv) - 1; + while (low <= high) + { + int mid = (low + high) / 2; + tree subvar = VEC_index (tree, sv, mid); + if (SFT_OFFSET (subvar) == offset) + return subvar; + else if (SFT_OFFSET (subvar) < offset) + low = mid + 1; + else + high = mid - 1; + } + + return NULL_TREE; +} + + +/* Return the first subvariable in SV that overlaps [offset, offset + size[. + NULL_TREE is returned, if there is no overlapping subvariable, else *I + is set to the index in the SV vector of the first overlap. */ + +static inline tree +get_first_overlapping_subvar (subvar_t sv, unsigned HOST_WIDE_INT offset, + unsigned HOST_WIDE_INT size, unsigned int *i) +{ + int low = 0; + int high = VEC_length (tree, sv) - 1; + int mid; tree subvar; - /* ??? Binary search would be possible here. */ - for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i) - if (SFT_OFFSET (subvar) == offset) + if (low > high) + return NULL_TREE; + + /* Binary search for offset. */ + do + { + mid = (low + high) / 2; + subvar = VEC_index (tree, sv, mid); + if (SFT_OFFSET (subvar) == offset) + { + *i = mid; + return subvar; + } + else if (SFT_OFFSET (subvar) < offset) + low = mid + 1; + else + high = mid - 1; + } + while (low <= high); + + /* As we didn't find a subvar with offset, adjust to return the + first overlapping one. */ + if (SFT_OFFSET (subvar) < offset + && SFT_OFFSET (subvar) + SFT_SIZE (subvar) <= offset) + { + mid += 1; + if ((unsigned)mid >= VEC_length (tree, sv)) + return NULL_TREE; + subvar = VEC_index (tree, sv, mid); + } + else if (SFT_OFFSET (subvar) > offset + && size <= SFT_OFFSET (subvar) - offset) + { + mid -= 1; + if (mid < 0) + return NULL_TREE; + subvar = VEC_index (tree, sv, mid); + } + + if (overlap_subvar (offset, size, subvar, NULL)) + { + *i = mid; return subvar; + } return NULL_TREE; } + /* Return true if V is a tree that we can have subvars for. Normally, this is any aggregate type. Also complex types which are not gimple registers can have subvars. */ diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c index 846fbb784eb..1203a47faab 100644 --- a/gcc/tree-ssa-operands.c +++ b/gcc/tree-ssa-operands.c @@ -1386,89 +1386,46 @@ access_can_touch_variable (tree ref, tree alias, HOST_WIDE_INT offset, 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. If AS_PTO is false, just add VAR to the vops. */ + SFT's for a structure. */ static bool -add_vars_for_offset (tree full_ref, tree var, HOST_WIDE_INT offset, - HOST_WIDE_INT size, bool is_call_site, bool is_def, - bool as_pto) +add_vars_for_offset (tree var, + unsigned HOST_WIDE_INT offset, unsigned HOST_WIDE_INT size, + bool is_def, bitmap mpt_vars) { bool added = false; + tree subvar; subvar_t sv; unsigned int i; - tree subvar; + /* Adjust offset by the pointed-to location. */ + offset += SFT_OFFSET (var); - /* Call-clobbered tags may have non-call-clobbered - symbols in their alias sets. Ignore them if we are - adding VOPs for a call site. */ - if (is_call_site && !is_call_clobbered (var)) + /* Add all subvars of var that overlap with the access. + Binary search for the first relevant SFT. */ + sv = get_subvars_for_var (SFT_PARENT_VAR (var)); + if (!get_first_overlapping_subvar (sv, offset, size, &i)) return false; - /* For SFTs we have to consider all subvariables of the parent var. */ - if (TREE_CODE (var) != STRUCT_FIELD_TAG - || !as_pto) + for (; VEC_iterate (tree, sv, i, subvar); ++i) { - /* If we do not know the full reference tree or if the access is - unspecified [0, -1], we cannot prune it. Otherwise try doing - so using access_can_touch_variable. */ - if (full_ref - && !(offset == 0 && size == -1) - && !access_can_touch_variable (full_ref, var, offset, size)) - return false; - - if (is_def) - append_vdef (var); - else - append_vuse (var); - return true; - } - - sv = get_subvars_for_var (SFT_PARENT_VAR (var)); - for (i = 0; VEC_iterate (tree, sv, i, subvar); ++i) - { - /* Once we hit the end of the parts that could touch, - stop looking. */ - if (size != -1 - && SFT_OFFSET (var) + offset + size <= SFT_OFFSET (subvar)) + if (size <= SFT_OFFSET (subvar) - offset) break; - if (overlap_subvar (SFT_OFFSET (var) + offset, size, subvar, NULL)) + + /* Avoid adding a SFT that is contained in the same MPT as the + pointed-to location as this MPT will be added as alias anyway. */ + if (!mpt_vars + || !bitmap_bit_p (mpt_vars, DECL_UID (subvar))) { - added = true; if (is_def) append_vdef (subvar); else append_vuse (subvar); } + added = true; } - return added; -} -/* Consider all SFTs in ALIASES as points-to location and add virtual - operands for the SFT parent var for the access FULL_REF at OFFSET - and size SIZE. IS_CALL_SITE is true if the stmt of the reference is - a call. IS_DEF is true if we should add VDEF virtual operands, - otherwise we'll add VUSEs. *NONE_ADDED is set to false once the first - virtual operand was added. */ - -static void -add_vars_for_bitmap (bitmap aliases, tree full_ref, - HOST_WIDE_INT offset, HOST_WIDE_INT size, - bool is_call_site, bool is_def, bool *none_added) -{ - bitmap_iterator bi; - unsigned int i; - - EXECUTE_IF_SET_IN_BITMAP (aliases, 0, i, bi) - { - tree al = referenced_var (i); - - gcc_assert (TREE_CODE (al) != MEMORY_PARTITION_TAG); - - if (TREE_CODE (al) == STRUCT_FIELD_TAG) - *none_added &= !add_vars_for_offset (full_ref, al, offset, size, - is_call_site, is_def, true); - } + return added; } /* Add VAR to the virtual operands array. FLAGS is as in @@ -1552,11 +1509,49 @@ add_virtual_operand (tree var, stmt_ann_t s_ann, int flags, But only if we start with NMT aliases. */ if (TREE_CODE (al) == MEMORY_PARTITION_TAG && TREE_CODE (var) == NAME_MEMORY_TAG) - add_vars_for_bitmap (MPT_SYMBOLS (al), full_ref, offset, size, - is_call_site, flags & opf_def, &none_added); - none_added &= !add_vars_for_offset (full_ref, al, offset, size, - is_call_site, flags & opf_def, - TREE_CODE (var) == NAME_MEMORY_TAG); + { + bitmap_iterator bi; + unsigned int i; + + EXECUTE_IF_SET_IN_BITMAP (MPT_SYMBOLS (al), 0, i, bi) + { + tree ptsft = referenced_var (i); + + if (TREE_CODE (ptsft) == STRUCT_FIELD_TAG) + none_added &= !add_vars_for_offset (ptsft, offset, size, + flags & opf_def, + MPT_SYMBOLS (al)); + } + } + + /* For SFTs we have to consider all subvariables of the parent var + 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, NULL); + else + { + /* Call-clobbered tags may have non-call-clobbered + symbols in their alias sets. Ignore them if we are + adding VOPs for a call site. */ + if (is_call_site && !is_call_clobbered (al)) + continue; + + /* If we do not know the full reference tree or if the access is + unspecified [0, -1], we cannot prune it. Otherwise try doing + so using access_can_touch_variable. */ + if (full_ref + && !(offset == 0 && size == -1) + && !access_can_touch_variable (full_ref, al, offset, size)) + continue; + + if (flags & opf_def) + append_vdef (al); + else + append_vuse (al); + none_added = false; + } } if (flags & opf_def) |