This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix another dead_debug* df-problems.c issue (PR debug/44023)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Paolo Bonzini <bonzini at gnu dot org>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 10 May 2010 19:14:38 +0200
- Subject: [PATCH] Fix another dead_debug* df-problems.c issue (PR debug/44023)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
df_note_bb_compute would apparently record using dead_debug_add just
the first use in a debug stmt that is no longer live, but if the
debug insn contains more than one such register, it would happily
keap that reference in after its REG_DEAD note (which leads to
-fcompare-debug failures in RA and probably a lot of potential problems
elsewhere too).
The following patch fixes that.
Unfortunately just the df_note_bb_compute change wasn't enough,
because Alex' code would immediately df_insn_rescan a debug insn
after updating it in dead_debug_insert_before. The first such an
update would free all the other uses and thus leaving garbage
in the chains (and not result in updating it for the second etc.
time). The patch solves it by deferring all debug insn rescans
from dead_debug_insert_before till dead_debug_finish.
Bootstrapped/regtested on x86_64-linux and i686-linux, Uros AFAIK
bootstrapped it on alpha*-linux.
Ok for trunk?
2010-05-10 Jakub Jelinek <jakub@redhat.com>
PR debug/44023
* df-problems.c (struct dead_debug): Add to_rescan field.
(dead_debug_init): Clear to_rescan field.
(dead_debug_finish): Rescan all debug insns in to_rescan
bitmap and free the bitmap.
(dead_debug_insert_before): Instead of rescanning debug insns
immediately queue their rescanning until dead_debug_finish.
(df_note_bb_compute): After dead_debug_add do continue instead
of break.
* gcc.dg/pr44023.c: New test.
--- gcc/df-problems.c.jj 2010-05-07 09:17:45.000000000 +0200
+++ gcc/df-problems.c 2010-05-10 11:54:10.000000000 +0200
@@ -3416,6 +3416,7 @@ struct dead_debug
{
struct dead_debug_use *head;
bitmap used;
+ bitmap to_rescan;
};
/* Initialize DEBUG to an empty list, and clear USED, if given. */
@@ -3424,6 +3425,7 @@ dead_debug_init (struct dead_debug *debu
{
debug->head = NULL;
debug->used = used;
+ debug->to_rescan = NULL;
if (used)
bitmap_clear (used);
}
@@ -3447,10 +3449,26 @@ dead_debug_finish (struct dead_debug *de
{
INSN_VAR_LOCATION_LOC (insn) = gen_rtx_UNKNOWN_VAR_LOC ();
df_insn_rescan_debug_internal (insn);
+ if (debug->to_rescan)
+ bitmap_clear_bit (debug->to_rescan, INSN_UID (insn));
}
debug->head = head->next;
XDELETE (head);
}
+
+ if (debug->to_rescan)
+ {
+ bitmap_iterator bi;
+ unsigned int uid;
+
+ EXECUTE_IF_SET_IN_BITMAP (debug->to_rescan, 0, uid, bi)
+ {
+ struct df_insn_info *insn_info = DF_INSN_UID_SAFE_GET (uid);
+ if (insn_info)
+ df_insn_rescan (insn_info->insn);
+ }
+ BITMAP_FREE (debug->to_rescan);
+ }
}
/* Add USE to DEBUG. It must be a dead reference to UREGNO in a debug
@@ -3530,7 +3548,9 @@ dead_debug_insert_before (struct dead_de
*DF_REF_REAL_LOC (cur->use)
= gen_lowpart_SUBREG (GET_MODE (*DF_REF_REAL_LOC (cur->use)), dval);
/* ??? Should we simplify subreg of subreg? */
- df_insn_rescan (DF_REF_INSN (cur->use));
+ if (debug->to_rescan == NULL)
+ debug->to_rescan = BITMAP_ALLOC (NULL);
+ bitmap_set_bit (debug->to_rescan, INSN_UID (DF_REF_INSN (cur->use)));
uses = cur->next;
XDELETE (cur);
}
@@ -3728,7 +3748,10 @@ df_note_bb_compute (unsigned int bb_inde
if (debug_insn)
{
if (debug_insn > 0)
- dead_debug_add (&debug, use, uregno);
+ {
+ dead_debug_add (&debug, use, uregno);
+ continue;
+ }
break;
}
else
--- gcc/testsuite/gcc.dg/pr44023.c.jj 2010-05-10 11:55:38.000000000 +0200
+++ gcc/testsuite/gcc.dg/pr44023.c 2010-05-10 11:57:39.000000000 +0200
@@ -0,0 +1,46 @@
+/* PR debug/44023 */
+/* { dg-do compile } */
+/* { dg-options "-fcompare-debug -O2" } */
+/* { dg-options "-fcompare-debug -O2 -mcpu=ev67" { target alpha*-*-* } } */
+
+void
+foo (unsigned f, long v, unsigned *w, unsigned a, unsigned b, unsigned e, unsigned c, unsigned d)
+{
+ unsigned h = v / 4, x[16];
+ while (f < h)
+ {
+ unsigned i;
+ f++;
+ a |= (a >> 30);
+ d = (d << 30) | ((unsigned) d >> 30);
+ c = (c << 30) | ((unsigned) c >> 30);
+ b = 30 | ((unsigned) b >> 30);
+ d += a = (a << 30) | ((unsigned) a >> 2);
+ c += ((d << 5) | (d >> 27)) + ((e & (a ^ b))) + 0x5a827999 + x[12];
+ a += (c & e);
+ c = 30 | ((unsigned) c);
+ i = x[5] ^ x[7] ^ x[8] ^ x[3];
+ x[5] = (i << 1) | ((unsigned) i >> 31);
+ i = x[6] ^ x[2] ^ x[14] ^ x[13];
+ x[6] = (i << 1) | (i >> 31);
+ b += (c | (c >> 5)) + (d ^ e) + 0x6ed9eba1 + (x[7] = (i << 1) | ((unsigned) i >> 31));
+ x[8] = i | 1;
+ e += (a | 5) + b + (i = x[9] ^ x[6], x[10] = (i << (unsigned) i));
+ e = 30 | ((unsigned) e >> 30);
+ i = x[12] ^ x[14] ^ x[12] ^ x[12], (x[12] = 1 | ((unsigned) i));
+ i = x[13] ^ x[5] ^ x[10], (x[13] = (i << (unsigned) 1));
+ i = x[2] ^ x[7] ^ x[12], (x[15] = i | ((unsigned) i >> 1));
+ i = x[2] ^ x[0] ^ x[13], (x[0] = (i << 1) | 31);
+ e = (e << 30) | 2;
+ i = x[14] ^ x[2] ^ x[15], (x[2] = i | 1);
+ x[3] = i | ((unsigned) i);
+ i = x[14] ^ x[12] ^ x[4], (x[4] = 1 | ((unsigned) i >> 1));
+ x[5] = i | 1;
+ e = (e << 30) | 30;
+ b += (5 | ((unsigned) e >> 5)) + 0x8f1bbcdc + (x[9] = (i | ((unsigned) i >> 1)));
+ i = x[2] ^ (x [10] = ((i << 1) | (i >> 1)));
+ x[13] = (i | ((unsigned) i >> 1));
+ (i = x[14] ^ x[0] ^ x[14], (x[14] = ((i << 1) | 31)));
+ a = *w += a;
+ }
+}
Jakub