summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2007-10-29 18:27:38 +0000
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>2007-10-29 18:27:38 +0000
commit8c5a45b9d761e701286ffc479a0a018cc96d890a (patch)
treec1b0567e0bc3a2faf2e843ff14afa359047427ee /gcc
parent0a39bce0303b563f5745b32c67aa925509b67226 (diff)
downloadgcc-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/ChangeLog12
-rw-r--r--gcc/tree-flow-inline.h79
-rw-r--r--gcc/tree-ssa-operands.c131
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)