Hi!

gen_rtx_SUBREG/gen_lowpart_SUBREG ICE when trying to create a subreg
the backend doesn't like, lowpart_subreg returns NULL.  But, for debug info
purposes, all lowpart subregs are valid, a subreg in the debug insns or
var-tracking notes is simply a mode punning construct, and even when the
backend doesn't have any instruction to perform such operation, the debugger
can always do the punning.

var-tracking.c already has code to emit gen_rtx_raw_SUBREG if everything
else fails, the following patch adjusts valtrack.c to do the same thing.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2015-04-07  Jakub Jelinek  <ja...@redhat.com>

        PR debug/65678
        * valtrack.c (debug_lowpart_subreg): New function.
        (dead_debug_insert_temp): Use it.

        * g++.dg/debug/pr65678.C: New test.

--- gcc/valtrack.c.jj   2015-01-05 13:07:14.000000000 +0100
+++ gcc/valtrack.c      2015-04-07 11:10:36.045912355 +0200
@@ -534,6 +534,22 @@ dead_debug_add (struct dead_debug_local
   bitmap_set_bit (debug->used, uregno);
 }
 
+/* Like lowpart_subreg, but if a subreg is not valid for machine, force
+   it anyway - for use in debug insns.  */
+
+static rtx
+debug_lowpart_subreg (machine_mode outer_mode, rtx expr,
+                     machine_mode inner_mode)
+{
+  if (inner_mode == VOIDmode)
+    inner_mode = GET_MODE (expr);
+  int offset = subreg_lowpart_offset (outer_mode, inner_mode);
+  rtx ret = simplify_gen_subreg (outer_mode, expr, inner_mode, offset);
+  if (ret)
+    return ret;
+  return gen_rtx_raw_SUBREG (outer_mode, expr, offset);
+}
+
 /* If UREGNO is referenced by any entry in DEBUG, emit a debug insn
    before or after INSN (depending on WHERE), that binds a (possibly
    global) debug temp to the widest-mode use of UREGNO, if WHERE is
@@ -662,9 +678,9 @@ dead_debug_insert_temp (struct dead_debu
          /* Ok, it's the same (hardware) REG, but with a different
             mode, so SUBREG it.  */
          else
-           breg = lowpart_subreg (GET_MODE (reg),
-                                  cleanup_auto_inc_dec (src, VOIDmode),
-                                  GET_MODE (dest));
+           breg = debug_lowpart_subreg (GET_MODE (reg),
+                                        cleanup_auto_inc_dec (src, VOIDmode),
+                                        GET_MODE (dest));
        }
       else if (GET_CODE (dest) == SUBREG)
        {
@@ -684,9 +700,9 @@ dead_debug_insert_temp (struct dead_debu
            breg = NULL;
          /* Yay, we can use SRC, just adjust its mode.  */
          else
-           breg = lowpart_subreg (GET_MODE (reg),
-                                  cleanup_auto_inc_dec (src, VOIDmode),
-                                  GET_MODE (dest));
+           breg = debug_lowpart_subreg (GET_MODE (reg),
+                                        cleanup_auto_inc_dec (src, VOIDmode),
+                                        GET_MODE (dest));
        }
       /* Oh well, we're out of luck.  */
       else
@@ -740,7 +756,8 @@ dead_debug_insert_temp (struct dead_debu
        *DF_REF_REAL_LOC (cur->use) = dval;
       else
        *DF_REF_REAL_LOC (cur->use)
-         = gen_lowpart_SUBREG (GET_MODE (*DF_REF_REAL_LOC (cur->use)), dval);
+         = debug_lowpart_subreg (GET_MODE (*DF_REF_REAL_LOC (cur->use)), dval,
+                                 GET_MODE (dval));
       /* ??? Should we simplify subreg of subreg?  */
       bitmap_set_bit (debug->to_rescan, INSN_UID (DF_REF_INSN (cur->use)));
       uses = cur->next;
--- gcc/testsuite/g++.dg/debug/pr65678.C.jj     2015-04-07 11:18:51.701891845 
+0200
+++ gcc/testsuite/g++.dg/debug/pr65678.C        2015-04-07 11:19:50.285943861 
+0200
@@ -0,0 +1,35 @@
+// PR debug/65678
+// { dg-do compile }
+
+long long v;
+
+static int
+bar (double x)
+{
+#if __SIZEOF_DOUBLE__ == __SIZEOF_LONG_LONG__
+  __builtin_memmove (&v, &x, sizeof v);
+#else
+  (void) x;
+  v = 0;
+#endif
+  return v;
+}
+
+struct A
+{
+  A (double x) : a (bar (x)) {}
+  int m1 ();
+  int m2 () { int b = a; return b; }
+  int a;
+};
+
+void foo ();
+
+void
+baz (double x)
+{
+  int c = A (x).m2 ();
+  int d = A (x).m1 ();
+  if (d)
+    foo ();
+}

        Jakub

Reply via email to