Commit 9044951e by Daniel Berlin Committed by Daniel Berlin

re PR tree-optimization/20458 (structure aliasing causes wrong code)

2005-03-14  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.

From-SVN: r96462
parent 50668cf6
2005-03-14 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.
2005-03-14 Geoffrey Keating <geoffk@apple.com> 2005-03-14 Geoffrey Keating <geoffk@apple.com>
* doc/cppopts.texi (-fexec-charset): Add concept index entry. * doc/cppopts.texi (-fexec-charset): Add concept index entry.
......
/* { 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;
}
...@@ -619,7 +619,7 @@ mark_call_clobbered (tree var) ...@@ -619,7 +619,7 @@ mark_call_clobbered (tree var)
variable. This is because the pointer that VAR represents has variable. This is because the pointer that VAR represents has
been found to point to either an arbitrary location or to a known been found to point to either an arbitrary location or to a known
location in global memory. */ 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; DECL_EXTERNAL (var) = 1;
bitmap_set_bit (call_clobbered_vars, ann->uid); bitmap_set_bit (call_clobbered_vars, ann->uid);
ssa_call_clobbered_cache_valid = false; ssa_call_clobbered_cache_valid = false;
...@@ -631,7 +631,7 @@ static inline void ...@@ -631,7 +631,7 @@ static inline void
clear_call_clobbered (tree var) clear_call_clobbered (tree var)
{ {
var_ann_t ann = var_ann (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; DECL_EXTERNAL (var) = 0;
bitmap_clear_bit (call_clobbered_vars, ann->uid); bitmap_clear_bit (call_clobbered_vars, ann->uid);
ssa_call_clobbered_cache_valid = false; ssa_call_clobbered_cache_valid = false;
......
...@@ -1729,7 +1729,7 @@ note_addressable (tree var, stmt_ann_t s_ann) ...@@ -1729,7 +1729,7 @@ note_addressable (tree var, stmt_ann_t s_ann)
if (s_ann->addresses_taken == NULL) if (s_ann->addresses_taken == NULL)
s_ann->addresses_taken = BITMAP_GGC_ALLOC (); s_ann->addresses_taken = BITMAP_GGC_ALLOC ();
bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid);
if (var_can_have_subvars (var) if (var_can_have_subvars (var)
&& (svars = get_subvars_for_var (var))) && (svars = get_subvars_for_var (var)))
{ {
...@@ -1737,6 +1737,8 @@ note_addressable (tree var, stmt_ann_t s_ann) ...@@ -1737,6 +1737,8 @@ note_addressable (tree var, stmt_ann_t s_ann)
for (sv = svars; sv; sv = sv->next) for (sv = svars; sv; sv = sv->next)
bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid); bitmap_set_bit (s_ann->addresses_taken, var_ann (sv->var)->uid);
} }
else
bitmap_set_bit (s_ann->addresses_taken, var_ann (var)->uid);
} }
} }
......
...@@ -137,14 +137,15 @@ suitable_for_tail_opt_p (void) ...@@ -137,14 +137,15 @@ suitable_for_tail_opt_p (void)
if (current_function_stdarg) if (current_function_stdarg)
return false; return false;
/* No local variable should be call-clobbered. We ignore any kind /* No local variable nor structure field should be call-clobbered. We
of memory tag, as these are not real variables. */ ignore any kind of memory tag, as these are not real variables. */
for (i = 0; i < (int) VARRAY_ACTIVE_SIZE (referenced_vars); i++) for (i = 0; i < (int) VARRAY_ACTIVE_SIZE (referenced_vars); i++)
{ {
tree var = VARRAY_TREE (referenced_vars, i); tree var = VARRAY_TREE (referenced_vars, i);
if (!(TREE_STATIC (var) || DECL_EXTERNAL (var)) 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)) && is_call_clobbered (var))
return false; return false;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment