diff mbox

Fix ICE in use_narrower_mode (PR debug/48967)

Message ID 20110511182633.GF17079@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek May 11, 2011, 6:26 p.m. UTC
Hi!

My http://gcc.gnu.org/ml/gcc-patches/2010-03/msg01379.html
debug info optimization (meant primarily for x86_64) as the following
testcase shows unfortunately breaks on powerpc64-linux and can in theory
everywhere where lowpart_subreg of some REG accepted by
use_narrower_mode_test isn't valid and thus returns NULL.

This patch fixes it by not optimizing if the SUBREG isn't valid.

Bootstrapped/regtested on x86_64-linux and i686-linux (where it never
hits though) and on the testcase on powerpc64-linux.

Ok for trunk/4.6?

2011-05-11  Jakub Jelinek  <jakub@redhat.com>

	PR debug/48967
	* var-tracking.c (use_narrower_mode_test) <case REG>: Return 1
	if validate_subreg fails.

	* g++.dg/opt/pr48967.C: New test.


	Jakub

Comments

Richard Biener May 12, 2011, 8:41 a.m. UTC | #1
On Wed, May 11, 2011 at 8:26 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> My http://gcc.gnu.org/ml/gcc-patches/2010-03/msg01379.html
> debug info optimization (meant primarily for x86_64) as the following
> testcase shows unfortunately breaks on powerpc64-linux and can in theory
> everywhere where lowpart_subreg of some REG accepted by
> use_narrower_mode_test isn't valid and thus returns NULL.
>
> This patch fixes it by not optimizing if the SUBREG isn't valid.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux (where it never
> hits though) and on the testcase on powerpc64-linux.
>
> Ok for trunk/4.6?

Ok.

Thanks,
Richard.

> 2011-05-11  Jakub Jelinek  <jakub@redhat.com>
>
>        PR debug/48967
>        * var-tracking.c (use_narrower_mode_test) <case REG>: Return 1
>        if validate_subreg fails.
>
>        * g++.dg/opt/pr48967.C: New test.
>
> --- gcc/var-tracking.c.jj       2011-05-11 19:39:04.000000000 +0200
> +++ gcc/var-tracking.c  2011-05-11 19:51:48.000000000 +0200
> @@ -745,6 +745,10 @@ use_narrower_mode_test (rtx *loc, void *
>     case REG:
>       if (cselib_lookup (*loc, GET_MODE (SUBREG_REG (subreg)), 0, VOIDmode))
>        return 1;
> +      if (!validate_subreg (GET_MODE (subreg), GET_MODE (*loc),
> +                           *loc, subreg_lowpart_offset (GET_MODE (subreg),
> +                                                        GET_MODE (*loc))))
> +       return 1;
>       return -1;
>     case PLUS:
>     case MINUS:
> --- gcc/testsuite/g++.dg/opt/pr48967.C.jj       2011-05-11 19:52:56.000000000 +0200
> +++ gcc/testsuite/g++.dg/opt/pr48967.C  2011-05-11 19:52:27.000000000 +0200
> @@ -0,0 +1,98 @@
> +// PR debug/48967
> +// { dg-do compile }
> +// { dg-options "-g -O2" }
> +
> +template <typename> struct A;
> +template <typename T> struct A <T *>
> +{
> +  typedef T ref;
> +};
> +template <typename T, typename> struct B
> +{
> +  typedef A <T> t;
> +  typedef typename t::ref ref;
> +  ref operator * () { return ref (); }
> +};
> +template <typename T> struct I
> +{
> +  typedef T *cp;
> +  template <typename T1> struct J
> +  {
> +    typedef I <T1> other;
> +  };
> +};
> +template <typename T> struct S : public I <T>
> +{
> +};
> +template <typename T, typename _A> struct E
> +{
> +  typedef typename _A::template J <T>::other at;
> +};
> +template <typename T, typename _A = S <T> > struct D
> +{
> +  typedef E <T, _A> _Base;
> +  typedef typename _Base::at at;
> +  typedef typename at::cp cp;
> +  typedef B <cp, D> H;
> +};
> +template <class T> struct F
> +{
> +  T *operator -> () { return __null; }
> +};
> +template <typename T> long
> +lfloor (T x)
> +{
> +  return static_cast <long>(x) - (x && x != static_cast <long>(x));
> +}
> +template <typename T> long
> +lround (T x)
> +{
> +  return lfloor (x - 0.5) + 1;
> +}
> +class M;
> +template <typename> class P;
> +typedef P <M> Q;
> +template <typename> struct P
> +{
> +  float x ();
> +};
> +struct CV
> +{
> +  Q c;
> +};
> +struct C
> +{
> +  void foo (const CV &) const;
> +  class O;
> +  typedef D <F <O> > R;
> +  R n;
> +};
> +struct S3
> +{
> +  S3 (int, int);
> +};
> +struct S2
> +{
> +  S3 sx, sy;
> +  S2 (int x = 0, int y = 0, int s = 0, int t = 0) : sx (x, y), sy (s, t) {}
> +};
> +template <typename> struct N
> +{
> +  int bar ();
> +};
> +struct C::O
> +{
> +  N <float> o;
> +  void foo (CV r, int)
> +  {
> +    Q c = r.c;
> +    float t = 0.5 * (o.bar ());
> +    S2 (lround (c.x ()), t);
> +  }
> +};
> +void
> +C::foo (const CV &w) const
> +{
> +  R::H m;
> +  (*m)->foo (w, 8);
> +}
>
>        Jakub
>
diff mbox

Patch

--- gcc/var-tracking.c.jj	2011-05-11 19:39:04.000000000 +0200
+++ gcc/var-tracking.c	2011-05-11 19:51:48.000000000 +0200
@@ -745,6 +745,10 @@  use_narrower_mode_test (rtx *loc, void *
     case REG:
       if (cselib_lookup (*loc, GET_MODE (SUBREG_REG (subreg)), 0, VOIDmode))
 	return 1;
+      if (!validate_subreg (GET_MODE (subreg), GET_MODE (*loc),
+			    *loc, subreg_lowpart_offset (GET_MODE (subreg),
+							 GET_MODE (*loc))))
+	return 1;
       return -1;
     case PLUS:
     case MINUS:
--- gcc/testsuite/g++.dg/opt/pr48967.C.jj	2011-05-11 19:52:56.000000000 +0200
+++ gcc/testsuite/g++.dg/opt/pr48967.C	2011-05-11 19:52:27.000000000 +0200
@@ -0,0 +1,98 @@ 
+// PR debug/48967
+// { dg-do compile }
+// { dg-options "-g -O2" }
+
+template <typename> struct A;
+template <typename T> struct A <T *>
+{
+  typedef T ref;
+};
+template <typename T, typename> struct B
+{
+  typedef A <T> t;
+  typedef typename t::ref ref;
+  ref operator * () { return ref (); }
+};
+template <typename T> struct I
+{
+  typedef T *cp;
+  template <typename T1> struct J
+  {
+    typedef I <T1> other;
+  };
+};
+template <typename T> struct S : public I <T>
+{
+};
+template <typename T, typename _A> struct E
+{
+  typedef typename _A::template J <T>::other at;
+};
+template <typename T, typename _A = S <T> > struct D
+{
+  typedef E <T, _A> _Base;
+  typedef typename _Base::at at;
+  typedef typename at::cp cp;
+  typedef B <cp, D> H;
+};
+template <class T> struct F
+{
+  T *operator -> () { return __null; }
+};
+template <typename T> long
+lfloor (T x)
+{
+  return static_cast <long>(x) - (x && x != static_cast <long>(x));
+}
+template <typename T> long
+lround (T x)
+{
+  return lfloor (x - 0.5) + 1;
+}
+class M;
+template <typename> class P;
+typedef P <M> Q;
+template <typename> struct P
+{
+  float x ();
+};
+struct CV
+{
+  Q c;
+};
+struct C
+{
+  void foo (const CV &) const;
+  class O;
+  typedef D <F <O> > R;
+  R n;
+};
+struct S3
+{
+  S3 (int, int);
+};
+struct S2
+{
+  S3 sx, sy;
+  S2 (int x = 0, int y = 0, int s = 0, int t = 0) : sx (x, y), sy (s, t) {}
+};
+template <typename> struct N
+{
+  int bar ();
+};
+struct C::O
+{
+  N <float> o;
+  void foo (CV r, int)
+  {
+    Q c = r.c;
+    float t = 0.5 * (o.bar ());
+    S2 (lround (c.x ()), t);
+  }
+};
+void
+C::foo (const CV &w) const
+{
+  R::H m;
+  (*m)->foo (w, 8);
+}