re PR debug/46240 (ice in maybe_register_def)

gcc/ChangeLog:
PR debug/46240
* tree-into-ssa.c (maybe_register_def): Do not attempt to add
debug bind stmt on merge edges.
gcc/testsuite/ChangeLog:
PR debug/46240
* g++.dg/debug/pr46240.cc: New.

From-SVN: r169035
This commit is contained in:
Alexandre Oliva 2011-01-19 22:07:14 +00:00 committed by Alexandre Oliva
parent 37d6a488a4
commit 23d5ed5dcf
4 changed files with 204 additions and 5 deletions

View File

@ -1,3 +1,9 @@
2011-01-19 Alexandre Oliva <aoliva@redhat.com>
PR debug/46240
* tree-into-ssa.c (maybe_register_def): Do not attempt to add
debug bind stmt on merge edges.
2011-01-19 Alexandre Oliva <aoliva@redhat.com>
PR debug/47079

View File

@ -1,3 +1,8 @@
2011-01-19 Alexandre Oliva <aoliva@redhat.com>
PR debug/46240
* g++.dg/debug/pr46240.cc: New.
2011-01-19 Jakub Jelinek <jakub@redhat.com>
PR c++/47303

View File

@ -0,0 +1,172 @@
// { dg-do compile }
// { dg-options "-O3 -g" }
template <typename T>
T &max (T &a, T &b)
{
if (a < b) return b; else return a;
}
int foo (double);
struct S
{
struct T
{
int dims, count;
T (int, int) : dims (), count () {}
};
T *rep;
S () {}
S (int r, int c) : rep (new T (r, c)) {}
~S () { delete rep; }
};
template <typename T>
struct U
{
static T epsilon () throw ();
};
template <class T>
struct V
{
struct W
{
T * data;
int count;
W (int n) : data (new T[n]), count () {}
};
V::W *rep;
S dimensions;
int slice_len;
V (S s) : rep (new V <T>::W (get_size (s))) {}
int capacity () { return slice_len; }
int get_size (S);
};
template <class T>
struct Z : public V <T>
{
Z () : V <T> (S (0, 0)) {}
Z (int r, int c) : V <T> (S (r, c)) {}
};
template <class T>
struct A : public Z <T>
{
A () : Z <T> () {}
A (int n, int m) : Z <T> (n, m) {}
};
template <class T>
struct B : public V <T>
{
};
struct C : public A <double>
{
C () : A <double> () {}
C (int r, int c) : A <double> (r, c) {}
};
struct D : public B <double>
{
};
template <class T>
struct E
{
};
template <class T>
struct G : public E <T>
{
};
struct H : public G <double>
{
};
template <class R>
struct I
{
R scl, sum;
void accum (R val)
{
R t = __builtin_fabs (val);
if (scl == t)
sum += 1;
}
operator R () { __builtin_sqrt (sum); return R (); }
};
template <class R>
struct J
{
template < class U > void accum (U val) {}
operator R () { return R (); }
};
template <class R>
struct K
{
R max;
template <class U> void accum (U val)
{
double z = __builtin_fabs (val);
max = ::max (max, z);
}
operator R () { return max; }
};
template <class R>
struct L
{
unsigned num;
template <class U> void accum (U) {}
operator R () { return num; }
};
template <class T, class R, class S>
void bar (V <T> &v, R &res, S acc)
{
for (int i = 0; i < v.capacity (); i++)
acc.accum ((i));
res = acc;
}
template <class T, class R>
void bar (B <T> &v, R)
{
R res;
bar (v, res, I <R> ());
}
template <class T, class R>
R bar (A <T> &v, R p)
{
R res;
if (p == 2)
bar (v, res, I <R> ());
else if (p == 1)
bar (v, res, J <R> ());
else if (p == sizeof (float) ? (p) : foo (p))
{
if (p > 0)
bar (v, res, K <R> ());
}
else if (p == 0)
bar (v, res, L <R> ());
return res;
}
template <class CT, class VectorT, class R>
void
baz (CT m, R p, R tol, int maxiter, VectorT)
{
VectorT y (0, 0), z (0, 1);
R q = 0;
R gamma = 0, gamma1 = 0;
gamma = bar (y, p);
(void) (bar (z, q) <= (gamma1 <= gamma));
}
int a = 100;
template <class CT, class VectorT, class R>
void
test (CT m, R p, VectorT)
{
VectorT x;
R sqrteps (U <R>::epsilon ());
baz (m, p, sqrteps, a, x);
}
void
fn (D x, double p)
{
bar (x, p);
}
void
fn (H x, double p)
{
test (x, p, C ());
}

View File

@ -1869,11 +1869,27 @@ maybe_register_def (def_operand_p def_p, gimple stmt,
gcc_assert (!ef);
ef = e;
}
gcc_assert (ef
&& single_pred_p (ef->dest)
&& !phi_nodes (ef->dest)
&& ef->dest != EXIT_BLOCK_PTR);
gsi_insert_on_edge_immediate (ef, note);
/* If there are other predecessors to ef->dest, then
there must be PHI nodes for the modified
variable, and therefore there will be debug bind
stmts after the PHI nodes. The debug bind notes
we'd insert would force the creation of a new
block (diverging codegen) and be redundant with
the post-PHI bind stmts, so don't add them.
As for the exit edge, there wouldn't be redundant
bind stmts, but there wouldn't be a PC to bind
them to either, so avoid diverging the CFG. */
if (ef && single_pred_p (ef->dest)
&& ef->dest != EXIT_BLOCK_PTR)
{
/* If there were PHI nodes in the node, we'd
have to make sure the value we're binding
doesn't need rewriting. But there shouldn't
be PHI nodes in a single-predecessor block,
so we just add the note. */
gsi_insert_on_edge_immediate (ef, note);
}
}
else
gsi_insert_after (&gsi, note, GSI_SAME_STMT);