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:
parent
08330ec2ad
commit
031905948a
|
@ -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
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
@ -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));
|
||||
}
|
|
@ -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)();
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue