re PR debug/65678 (internal compiler error: in gen_rtx_SUBREG, at emit-rtl.c:909)
authorJakub Jelinek <jakub@redhat.com>
Tue, 7 Apr 2015 14:35:18 +0000 (16:35 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 7 Apr 2015 14:35:18 +0000 (16:35 +0200)
PR debug/65678
* valtrack.c (debug_lowpart_subreg): New function.
(dead_debug_insert_temp): Use it.

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

From-SVN: r221900

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/debug/pr65678.C [new file with mode: 0644]
gcc/valtrack.c

index dcb7e99..d4bf73a 100644 (file)
@@ -1,5 +1,9 @@
 2015-04-07  Jakub Jelinek  <jakub@redhat.com>
 
+       PR debug/65678
+       * valtrack.c (debug_lowpart_subreg): New function.
+       (dead_debug_insert_temp): Use it.
+
        PR middle-end/65680
        * expr.c (get_inner_reference): Handle bit_offset that doesn't fit
        into signed HOST_WIDE_INT the same as negative bit_offset.
index 933da2c..6d8ce37 100644 (file)
@@ -1,5 +1,8 @@
 2015-04-07  Jakub Jelinek  <jakub@redhat.com>
 
+       PR debug/65678
+       * g++.dg/debug/pr65678.C: New test.
+
        PR middle-end/65680
        * gcc.c-torture/compile/pr65680.c: New test.
 
diff --git a/gcc/testsuite/g++.dg/debug/pr65678.C b/gcc/testsuite/g++.dg/debug/pr65678.C
new file mode 100644 (file)
index 0000000..d99c73b
--- /dev/null
@@ -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 ();
+}
index 804b8e8..3dfb8a9 100644 (file)
@@ -534,6 +534,22 @@ dead_debug_add (struct dead_debug_local *debug, df_ref use, unsigned int uregno)
   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_debug_local *debug, unsigned int uregno,
          /* 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_debug_local *debug, unsigned int uregno,
            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_debug_local *debug, unsigned int uregno,
        *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;