This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Fix PR 20458 and regressions on i686/x86-64/ppc
- From: Daniel Berlin <dberlin at dberlin dot org>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 13 Mar 2005 23:28:15 -0500
- Subject: [PATCH]: Fix PR 20458 and regressions on i686/x86-64/ppc
The attached patch fixes all the structure aliasing regressions that
have been pointed out so far.
There were three related problems.
1. We don't keep the call clobbering status of the original variable up
to date when we have SFT's for it.
This is/was by design, because
a. no optimizers are supposed to be looking at the original variable
when it has subvars.
b. Keeping the original variable up to date would require some extra
places to look at subvars to make sure the original variable didn't get
thrown into the vops for calls if it had subvars (since it shouldn't be
there, only the SFT's should)
c. It's enough to make sure the call clobbering status of the SFT's is
correct, and that the SFT's get added to calls when approriate, which we
do. IE Putting the original variable in the call clobber ops doesn't
help anything anyway.
d. Before someone asks, we do keep the TREE_ADDRESSABLE flag correctly
set (IE clear only iff all subvars are non-addressable) on the original
variable, so that later parts of the compiler don't get confused when
the SFT's go away. None of these parts check the call clobbered
bitmaps.
The problem in 20031015-1 was that the original variable snuck into a
call clobber bitmap anyway, so we ended up with call clobbers for both
the original, and the SFT, which, while not hurting anything, is one
more vop than expected.
This may have been a bad decision, in hindsight, and we should just take
the performance hit for keeping it up to date. However, again, nothing
is supposed to be checking it when we have subvars, and we don't want
the original variable in the clobber lists for calls anyway, so this
performance hit doesn't actually buy us anything.
2. We like to fiddle with DECL_EXTERNAL on tags depending on their call
clobbered-ness. This is wrong for STRUCT_FIELD's, which should retain
the DECL_EXTERNAL of their original variable, always.
3. tree tailcall walks all the referenced vars to see if any local vars
are call clobbered, and specifically skips mem-tags.
This doesn't work when STRUCT_FIELDs are mem-tags, and the original
variable had it's call clobbered bit cleared but the SFT's are still
correctly call clobbered.
I'm happy to prepare a followup patch to add the necessary loops if we
want to try to keep the call clobbered status of the original variables
up to date.
In the meanwhile, this fixes the regressions (all but the tailcall
portion would be necessary in the presence of such a followup).
Bootstrapped and regtested on i686-pc-linux-gnu and x86-64-linux-gnu
(which had the same failures as ppc, apparently, plus the 20458 failure)
Bootstrap and regtesting on ppc is still going on.
Okay assuming ppc regtests pass?
--Dan
2005-03-13 Daniel Berlin <dberlin@dberlin.org>
Fix PR tree-optimization/20458
* tree-flow-inline.h (mark_call_clobbered): Don't fiddle
DECL_EXTERNAL on STRUCT_FIELD tags.
(clear_call_clobbered): Ditto.
* tree-ssa-operands.c (note_addressable): Make sure the original
variable doesn't slip into the addressable list if we have
subvars.
* tree-tailcall.c (suitable_for_tail_opt_p): Look at STRUCT_FIELD
tags too.
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow-inline.h,v
retrieving revision 2.32
diff -u -p -r2.32 tree-flow-inline.h
--- tree-flow-inline.h 13 Mar 2005 00:45:51 -0000 2.32
+++ tree-flow-inline.h 14 Mar 2005 04:07:44 -0000
@@ -619,7 +619,7 @@ mark_call_clobbered (tree var)
variable. This is because the pointer that VAR represents has
been found to point to either an arbitrary location or to a known
location in global memory. */
- if (ann->mem_tag_kind != NOT_A_TAG)
+ if (ann->mem_tag_kind != NOT_A_TAG && ann->mem_tag_kind != STRUCT_FIELD)
DECL_EXTERNAL (var) = 1;
bitmap_set_bit (call_clobbered_vars, ann->uid);
ssa_call_clobbered_cache_valid = false;
@@ -631,7 +631,7 @@ static inline void
clear_call_clobbered (tree var)
{
var_ann_t ann = var_ann (var);
- if (ann->mem_tag_kind != NOT_A_TAG)
+ if (ann->mem_tag_kind != NOT_A_TAG && ann->mem_tag_kind != STRUCT_FIELD)
DECL_EXTERNAL (var) = 0;
bitmap_clear_bit (call_clobbered_vars, ann->uid);
ssa_call_clobbered_cache_valid = false;
Index: tree-ssa-operands.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-operands.c,v
retrieving revision 2.66
diff -u -p -r2.66 tree-ssa-operands.c
--- tree-ssa-operands.c 13 Mar 2005 00:45:53 -0000 2.66
+++ tree-ssa-operands.c 14 Mar 2005 04:07:45 -0000
@@ -1727,7 +1727,7 @@ note_addressable (tree var, stmt_ann_t s
if (s_ann->addresses_taken == NULL)
s_ann->addresses_taken = BITMAP_GGC_ALLOC ();
- bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid);
+
if (var_can_have_subvars (var)
&& (svars = get_subvars_for_var (var)))
{
@@ -1735,6 +1735,8 @@ note_addressable (tree var, stmt_ann_t s
for (sv = svars; sv; sv = sv->next)
bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid);
}
+ else
+ bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid);
}
}
Index: tree-tailcall.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-tailcall.c,v
retrieving revision 2.37
diff -u -p -r2.37 tree-tailcall.c
--- tree-tailcall.c 11 Mar 2005 09:05:12 -0000 2.37
+++ tree-tailcall.c 14 Mar 2005 04:07:45 -0000
@@ -137,14 +137,15 @@ suitable_for_tail_opt_p (void)
if (current_function_stdarg)
return false;
- /* No local variable should be call-clobbered. We ignore any kind
- of memory tag, as these are not real variables. */
+ /* No local variable should be call-clobbered. We ignore any kind of memory
+ tag except structure fields, as these are not real variables. */
for (i = 0; i < (int) VARRAY_ACTIVE_SIZE (referenced_vars); i++)
{
tree var = VARRAY_TREE (referenced_vars, i);
if (!(TREE_STATIC (var) || DECL_EXTERNAL (var))
- && var_ann (var)->mem_tag_kind == NOT_A_TAG
+ && (var_ann (var)->mem_tag_kind == NOT_A_TAG
+ || var_ann (var)->mem_tag_kind == STRUCT_FIELD)
&& is_call_clobbered (var))
return false;
}
Index: testsuite/g++.dg/tree-ssa/pr20458.C
===================================================================
RCS file: testsuite/g++.dg/tree-ssa/pr20458.C
diff -N testsuite/g++.dg/tree-ssa/pr20458.C
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ testsuite/g++.dg/tree-ssa/pr20458.C 14 Mar 2005 04:07:49 -0000
@@ -0,0 +1,37 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+/* The tail call optimization would inapproriately tail call the
+ destructors due to not recognizing a call clobbered variable */
+namespace std
+{
+ class locale
+ {
+ public:
+ locale();
+ ~locale();
+ };
+}
+
+struct B
+{
+ std::locale _M_buf_locale;
+ virtual ~B() {}
+};
+
+struct C : public B
+{
+ char *s;
+};
+
+void foo ()
+{
+ C c;
+}
+
+int main()
+{
+ foo ();
+ return 0;
+}
+