This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix up creation of lowpart subregs in valtrack (PR debug/65678)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Biener <rguenther at suse dot de>, Alexandre Oliva <aoliva at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Tue, 7 Apr 2015 16:23:11 +0200
- Subject: [PATCH] Fix up creation of lowpart subregs in valtrack (PR debug/65678)
- Authentication-results: sourceware.org; auth=none
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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 <jakub@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