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  <ja...@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

Reply via email to