re PR tree-optimization/24351 (ICE in do_simple_structure_copy with some C++ code)

2005-11-03  Daniel Berlin  <dberlin@dberlin.org>

	Fix PR tree-optimization/24351

	* tree-ssa-structalias.c (struct variable_info): Add
	collapsed_into.
	(get_varinfo_fc): New function to follow collapsing.
	(new_var_info): Set collapsed_to to NULL.
	(dump_constraint): Follow collapsing.
	(build_constraint_graph): Handle collapsing.
	(do_simple_structure_copy): Return false if something bad
	happened.
	(collapse_rest_of_var): New function.
	(do_structure_copy): Collapse if do_simple_structure_copy returns
	false.

From-SVN: r106437
This commit is contained in:
Daniel Berlin 2005-11-03 15:39:48 +00:00 committed by Daniel Berlin
parent 08330ec2ad
commit 031905948a
5 changed files with 245 additions and 15 deletions

View File

@ -1,3 +1,19 @@
2005-11-03 Daniel Berlin <dberlin@dberlin.org>
Fix PR tree-optimization/24351
* tree-ssa-structalias.c (struct variable_info): Add
collapsed_into.
(get_varinfo_fc): New function to follow collapsing.
(new_var_info): Set collapsed_to to NULL.
(dump_constraint): Follow collapsing.
(build_constraint_graph): Handle collapsing.
(do_simple_structure_copy): Return false if something bad
happened.
(collapse_rest_of_var): New function.
(do_structure_copy): Collapse if do_simple_structure_copy returns
false.
2005-11-03 Andrew Pinski <pinskia@physics.uc.edu>
PR middle-end/24589

View File

@ -0,0 +1,24 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
struct adaptor_base {
};
struct bound_argument {
bound_argument();
};
template <class T_functor> struct adaptor_functor : public adaptor_base {
explicit adaptor_functor(const T_functor& _A_functor) : functor_(_A_functor)
{
}
T_functor functor_;
bound_argument bound_;
};
template <class T_functor> struct adapts : public adaptor_base {
explicit adapts(const T_functor& _A_functor) : functor_(_A_functor) {
}
adaptor_functor<T_functor> functor_;
};
int main() {
adapts<adapts<int> > a (adapts<int>(1));
}

View File

@ -0,0 +1,25 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
struct adaptor_base {};
struct bound_argument {
bound_argument();
};
struct adaptor_functorint : public adaptor_base {};
struct adaptsint : public adaptor_base {
adaptsint(const int& _A_functor);
adaptor_functorint functor_;
};
struct adaptor_functor_adaptsint {
adaptor_functor_adaptsint(const adaptsint& _A_functor) : functor_(_A_functor)
{}
adaptsint functor_;
bound_argument bound_;
};
struct adapts_adaptsint {
adapts_adaptsint(const adaptsint& _A_functor) : functor_(_A_functor)
{}
adaptor_functor_adaptsint functor_;
};
int main() {
adapts_adaptsint a (adaptsint(1));
}

View File

@ -0,0 +1,101 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
namespace sigc {
template <class T_type> struct type_trait {
typedef T_type& pass;
typedef const T_type& take;
typedef T_type* pointer;
};
template <class T_type> struct type_trait<T_type&> {
typedef T_type& pass;
};
template<> struct type_trait<void> {
typedef void pass;
};
template <class T_base, class T_derived> struct is_base_and_derived {
struct big {
char memory[64];
};
static big is_base_class_(...);
static char is_base_class_(typename type_trait<T_base>::pointer);
static const bool value = sizeof(is_base_class_(reinterpret_cast<typename type_trait<T_derived>::pointer>(0))) == sizeof(char);
};
struct nil;
struct functor_base {
};
template <class T_functor, bool I_derives_functor_base=is_base_and_derived<functor_base,T_functor>::value> struct functor_trait {
typedef typename T_functor::result_type result_type;
typedef T_functor functor_type;
};
struct adaptor_base : public functor_base {
};
template <class T_functor, class T_arg1=void,class T_arg2=void,class T_arg3=void,class T_arg4=void,class T_arg5=void,class T_arg6=void,class T_arg7=void, bool I_derives_adaptor_base=is_base_and_derived<adaptor_base,T_functor>::value> struct deduce_result_type {
typedef typename functor_trait<T_functor>::result_type type;
};
template <class T_functor> struct adaptor_functor
: public adaptor_base {
template <class T_arg1=void,class T_arg2=void,class T_arg3=void,class T_arg4=void,class T_arg5=void,class T_arg6=void,class T_arg7=void> struct deduce_result_type {
typedef typename sigc::deduce_result_type<T_functor, T_arg1,T_arg2,T_arg3,T_arg4,T_arg5,T_arg6,T_arg7>::type type;
};
typedef typename functor_trait<T_functor>::result_type result_type;
template <class T_arg1,class T_arg2> typename deduce_result_type<T_arg1,T_arg2>::type operator()(T_arg1 _A_arg1,T_arg2 _A_arg2) const {
return functor_(_A_arg1,_A_arg2);
}
explicit adaptor_functor(const T_functor& _A_functor) : functor_(_A_functor) {
}
mutable T_functor functor_;
};
template <class T_functor, bool I_isadaptor = is_base_and_derived<adaptor_base, T_functor>::value> struct adaptor_trait;
template <class T_functor> struct adaptor_trait<T_functor, true> {
typedef T_functor adaptor_type;
};
template <class T_functor> struct adaptor_trait<T_functor, false> {
typedef typename functor_trait<T_functor>::functor_type functor_type;
typedef adaptor_functor<functor_type> adaptor_type;
};
template <class T_functor> struct adapts
: public adaptor_base {
typedef typename adaptor_trait<T_functor>::adaptor_type adaptor_type;
explicit adapts(const T_functor& _A_functor) : functor_(_A_functor) {
}
mutable adaptor_type functor_;
};
template <class T_type> struct unwrap_reference {
typedef T_type type;
};
template <class T_type> class bound_argument {
public:
bound_argument(const T_type& _A_argument) : visited_(_A_argument) {
}
inline T_type& invoke() {
}
T_type visited_;
};
template <int I_location, class T_functor, class T_type1=nil,class T_type2=nil,class T_type3=nil,class T_type4=nil,class T_type5=nil,class T_type6=nil,class T_type7=nil> struct bind_functor;
template <class T_functor, class T_bound> struct bind_functor<0, T_functor, T_bound, nil,nil,nil,nil,nil,nil> : public adapts<T_functor> {
typedef typename adapts<T_functor>::adaptor_type adaptor_type;
template <class T_arg1=void,class T_arg2=void,class T_arg3=void,class T_arg4=void,class T_arg5=void,class T_arg6=void,class T_arg7=void> struct deduce_result_type {
typedef typename adaptor_type::template deduce_result_type<typename type_trait<typename unwrap_reference<T_bound>::type>::pass, typename type_trait<T_arg1>::pass, typename type_trait<T_arg2>::pass, typename type_trait<T_arg3>::pass, typename type_trait<T_arg4>::pass, typename type_trait<T_arg5>::pass, typename type_trait<T_arg6>::pass>::type type;
};
typedef typename adaptor_type::result_type result_type;
result_type operator()() {
return this->functor_.template operator()<typename type_trait<typename unwrap_reference<T_bound>::type>::pass> (bound_.invoke());
}
template <class T_arg1> typename deduce_result_type<T_arg1>::type operator()(T_arg1 _A_arg1) {
return this->functor_.template operator()<typename type_trait<typename unwrap_reference<T_bound>::type>::pass, typename type_trait<T_arg1>::pass> (bound_.invoke(), _A_arg1);
}
bind_functor(typename type_trait<T_functor>::take _A_func, typename type_trait<T_bound>::take _A_bound) : adapts<T_functor>(_A_func), bound_(_A_bound) {
}
bound_argument<T_bound> bound_;
};
template <int I_location, class T_bound1, class T_functor> inline bind_functor<I_location, T_functor, T_bound1> bind(const T_functor& _A_func, T_bound1 _A_b1) {
return bind_functor<I_location, T_functor, T_bound1>(_A_func, _A_b1);
};
}
struct foo {
typedef int result_type;
int operator()(int i, int j);
};
int main() {
sigc::bind<0>(sigc::bind<0>(foo(),7),8)();
}

View File

@ -239,6 +239,11 @@ struct variable_info
/* Vector of complex constraints for this node. Complex
constraints are those involving dereferences. */
VEC(constraint_t,heap) *complex;
/* Variable id this was collapsed to due to type unsafety.
This should be unused completely after build_constraint_graph, or
something is broken. */
struct variable_info *collapsed_to;
};
typedef struct variable_info *varinfo_t;
@ -258,11 +263,23 @@ static VEC(varinfo_t,heap) *varmap;
/* Return the varmap element N */
static inline varinfo_t
get_varinfo(unsigned int n)
get_varinfo (unsigned int n)
{
return VEC_index(varinfo_t, varmap, n);
}
/* Return the varmap element N, following the collapsed_to link. */
static inline varinfo_t
get_varinfo_fc (unsigned int n)
{
varinfo_t v = VEC_index(varinfo_t, varmap, n);
if (v->collapsed_to)
return v->collapsed_to;
return v;
}
/* Variable that represents the unknown pointer. */
static varinfo_t var_anything;
static tree anything_tree;
@ -316,6 +333,7 @@ new_var_info (tree t, unsigned int id, const char *name, unsigned int node)
bitmap_clear (ret->variables);
ret->complex = NULL;
ret->next = NULL;
ret->collapsed_to = NULL;
return ret;
}
@ -429,7 +447,7 @@ dump_constraint (FILE *file, constraint_t c)
fprintf (file, "&");
else if (c->lhs.type == DEREF)
fprintf (file, "*");
fprintf (file, "%s", get_varinfo (c->lhs.var)->name);
fprintf (file, "%s", get_varinfo_fc (c->lhs.var)->name);
if (c->lhs.offset != 0)
fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->lhs.offset);
fprintf (file, " = ");
@ -437,7 +455,7 @@ dump_constraint (FILE *file, constraint_t c)
fprintf (file, "&");
else if (c->rhs.type == DEREF)
fprintf (file, "*");
fprintf (file, "%s", get_varinfo (c->rhs.var)->name);
fprintf (file, "%s", get_varinfo_fc (c->rhs.var)->name);
if (c->rhs.offset != 0)
fprintf (file, " + " HOST_WIDE_INT_PRINT_DEC, c->rhs.offset);
fprintf (file, "\n");
@ -982,33 +1000,36 @@ build_constraint_graph (void)
{
struct constraint_expr lhs = c->lhs;
struct constraint_expr rhs = c->rhs;
unsigned int lhsvar = get_varinfo_fc (lhs.var)->id;
unsigned int rhsvar = get_varinfo_fc (rhs.var)->id;
if (lhs.type == DEREF)
{
/* *x = y or *x = &y (complex) */
if (rhs.type == ADDRESSOF || rhs.var > anything_id)
insert_into_complex (lhs.var, c);
if (rhs.type == ADDRESSOF || rhsvar > anything_id)
insert_into_complex (lhsvar, c);
}
else if (rhs.type == DEREF)
{
/* !special var= *y */
if (!(get_varinfo (lhs.var)->is_special_var))
insert_into_complex (rhs.var, c);
if (!(get_varinfo (lhsvar)->is_special_var))
insert_into_complex (rhsvar, c);
}
else if (rhs.type == ADDRESSOF)
{
/* x = &y */
bitmap_set_bit (get_varinfo (lhs.var)->solution, rhs.var);
bitmap_set_bit (get_varinfo (lhsvar)->solution, rhsvar);
}
else if (lhs.var > anything_id)
else if (lhsvar > anything_id)
{
/* Ignore 0 weighted self edges, as they can't possibly contribute
anything */
if (lhs.var != rhs.var || rhs.offset != 0 || lhs.offset != 0)
if (lhsvar != rhsvar || rhs.offset != 0 || lhs.offset != 0)
{
struct constraint_edge edge;
edge.src = lhs.var;
edge.dest = rhs.var;
edge.src = lhsvar;
edge.dest = rhsvar;
/* x = y (simple) */
add_graph_edge (graph, edge);
bitmap_set_bit (get_graph_weights (graph, edge),
@ -2300,9 +2321,12 @@ get_constraint_for (tree t, bool *need_anyoffset)
For each field of the lhs variable (lhsfield)
For each field of the rhs variable at lhsfield.offset (rhsfield)
add the constraint lhsfield = rhsfield
*/
static void
If we fail due to some kind of type unsafety or other thing we
can't handle, return false. We expect the caller to collapse the
variable in that case. */
static bool
do_simple_structure_copy (const struct constraint_expr lhs,
const struct constraint_expr rhs,
const unsigned HOST_WIDE_INT size)
@ -2322,9 +2346,12 @@ do_simple_structure_copy (const struct constraint_expr lhs,
q = get_varinfo (temprhs.var);
fieldoffset = p->offset - pstart;
q = first_vi_for_offset (q, q->offset + fieldoffset);
if (!q)
return false;
temprhs.var = q->id;
process_constraint (new_constraint (templhs, temprhs));
}
return true;
}
@ -2406,6 +2433,32 @@ do_lhs_deref_structure_copy (const struct constraint_expr lhs,
}
}
/* Sometimes, frontends like to give us bad type information. This
function will collapse all the fields from VAR to the end of VAR,
into VAR, so that we treat those fields as a single variable.
We return the variable they were collapsed into. */
static unsigned int
collapse_rest_of_var (unsigned int var)
{
varinfo_t currvar = get_varinfo (var);
varinfo_t field;
for (field = currvar->next; field; field = field->next)
{
if (dump_file)
fprintf (dump_file, "Type safety: Collapsing var %s into %s\n",
field->name, currvar->name);
gcc_assert (!field->collapsed_to);
field->collapsed_to = currvar;
}
currvar->next = NULL;
currvar->size = currvar->fullsize - currvar->offset;
return currvar->id;
}
/* Handle aggregate copies by expanding into copies of the respective
fields of the structures. */
@ -2492,7 +2545,18 @@ do_structure_copy (tree lhsop, tree rhsop)
if (rhs.type == SCALAR && lhs.type == SCALAR)
do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
{
if (!do_simple_structure_copy (lhs, rhs, MIN (lhssize, rhssize)))
{
lhs.var = collapse_rest_of_var (lhs.var);
rhs.var = collapse_rest_of_var (rhs.var);
lhs.offset = 0;
rhs.offset = 0;
lhs.type = SCALAR;
rhs.type = SCALAR;
process_constraint (new_constraint (lhs, rhs));
}
}
else if (lhs.type != DEREF && rhs.type == DEREF)
do_rhs_deref_structure_copy (lhs, rhs, MIN (lhssize, rhssize));
else if (lhs.type == DEREF && rhs.type != DEREF)