[PATCH] Fix VTA updating in the combiner (PR debug/48343)
Jakub Jelinek
jakub@redhat.com
Wed Mar 30 20:11:00 GMT 2011
Hi!
We ICE on the attached testcase, because combiner changes mode of
a pseudo (which was set just once and used once plus in debug insns)
from SImode to QImode, but the uses in debug insns aren't adjusted.
Combiner has code to adjust this too (propagate_for_debug), but only updates
debug insns between i2 and i3 (resp. i3 and undobuf.other_insn).
The problem on the testcase is that this is a retry, so first
try_combine with a later i3 calls propagate_for_debug and changes debug
insns before that later i3, then returns an earlier insn that should be
retried and we stop adjusting debug insns at that earlier i3. Unfortunately
as later debug insns have been already updated earlier, they need to be
adjusted too.
The following patch fixes that by always stopping on the latest i3 that has
been successfully combined into in the current bb, bootstrapped/regtested
on x86_64-linux and i686-linux, ok for trunk/4.6?
2011-03-30 Jakub Jelinek <jakub@redhat.com>
PR debug/48343
* combine.c (last_combined_insn): New variable.
(combine_instructions): Clear it before processing each bb
and after last bb.
(try_combine): Set it to i3 if i3 is after it.
Use it as the last argument to propagate_for_debug instead
of i3.
(distribute_notes): Assert SET_INSN_DELETE is not called
on last_combined_insn.
* gcc.dg/torture/pr48343.c: New test.
--- gcc/combine.c.jj 2011-03-23 09:34:40.000000000 +0100
+++ gcc/combine.c 2011-03-30 17:39:09.000000000 +0200
@@ -337,6 +337,9 @@ static enum machine_mode nonzero_bits_mo
static int nonzero_sign_valid;
+/* Last insn on which try_combine has been called in the current BB. */
+
+static rtx last_combined_insn;
/* Record one modification to rtl structure
to be undone by storing old_contents into *where. */
@@ -1168,6 +1171,7 @@ combine_instructions (rtx f, unsigned in
|| single_pred (this_basic_block) != last_bb)
label_tick_ebb_start = label_tick;
last_bb = this_basic_block;
+ last_combined_insn = NULL_RTX;
rtl_profile_for_bb (this_basic_block);
for (insn = BB_HEAD (this_basic_block);
@@ -1379,6 +1383,7 @@ combine_instructions (rtx f, unsigned in
}
}
+ last_combined_insn = NULL_RTX;
default_rtl_profile ();
clear_log_links ();
clear_bb_flags ();
@@ -3830,6 +3835,10 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
return 0;
}
+ if (last_combined_insn == NULL_RTX
+ || DF_INSN_LUID (last_combined_insn) < DF_INSN_LUID (i3))
+ last_combined_insn = i3;
+
if (MAY_HAVE_DEBUG_INSNS)
{
struct undo *undo;
@@ -3851,7 +3860,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
i2src while its original mode is temporarily
restored, and then clear i2scratch so that we don't
do it again later. */
- propagate_for_debug (i2, i3, reg, i2src);
+ propagate_for_debug (i2, last_combined_insn, reg, i2src);
i2scratch = false;
/* Put back the new mode. */
adjust_reg_mode (reg, new_mode);
@@ -3859,18 +3868,17 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
else
{
rtx tempreg = gen_raw_REG (old_mode, REGNO (reg));
- rtx first, last;
+ rtx first;
if (reg == i2dest)
- {
- first = i2;
- last = i3;
- }
+ first = i2;
else
{
first = i3;
- last = undobuf.other_insn;
- gcc_assert (last);
+ gcc_assert (undobuf.other_insn);
+ if (DF_INSN_LUID (undobuf.other_insn)
+ > DF_INSN_LUID (last_combined_insn))
+ last_combined_insn = undobuf.other_insn;
}
/* We're dealing with a reg that changed mode but not
@@ -3882,9 +3890,9 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
with this copy we have created; then, replace the
copy with the SUBREG of the original shared reg,
once again changed to the new mode. */
- propagate_for_debug (first, last, reg, tempreg);
+ propagate_for_debug (first, last_combined_insn, reg, tempreg);
adjust_reg_mode (reg, new_mode);
- propagate_for_debug (first, last, tempreg,
+ propagate_for_debug (first, last_combined_insn, tempreg,
lowpart_subreg (old_mode, reg, new_mode));
}
}
@@ -4099,14 +4107,14 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
if (newi2pat)
{
if (MAY_HAVE_DEBUG_INSNS && i2scratch)
- propagate_for_debug (i2, i3, i2dest, i2src);
+ propagate_for_debug (i2, last_combined_insn, i2dest, i2src);
INSN_CODE (i2) = i2_code_number;
PATTERN (i2) = newi2pat;
}
else
{
if (MAY_HAVE_DEBUG_INSNS && i2src)
- propagate_for_debug (i2, i3, i2dest, i2src);
+ propagate_for_debug (i2, last_combined_insn, i2dest, i2src);
SET_INSN_DELETED (i2);
}
@@ -4115,7 +4123,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
LOG_LINKS (i1) = 0;
REG_NOTES (i1) = 0;
if (MAY_HAVE_DEBUG_INSNS)
- propagate_for_debug (i1, i3, i1dest, i1src);
+ propagate_for_debug (i1, last_combined_insn, i1dest, i1src);
SET_INSN_DELETED (i1);
}
@@ -4124,7 +4132,7 @@ try_combine (rtx i3, rtx i2, rtx i1, rtx
LOG_LINKS (i0) = 0;
REG_NOTES (i0) = 0;
if (MAY_HAVE_DEBUG_INSNS)
- propagate_for_debug (i0, i3, i0dest, i0src);
+ propagate_for_debug (i0, last_combined_insn, i0dest, i0src);
SET_INSN_DELETED (i0);
}
@@ -13454,6 +13462,7 @@ distribute_notes (rtx notes, rtx from_in
NULL_RTX, NULL_RTX, NULL_RTX);
distribute_links (LOG_LINKS (tem));
+ gcc_assert (tem != last_combined_insn);
SET_INSN_DELETED (tem);
if (tem == i2)
i2 = NULL_RTX;
@@ -13471,6 +13480,7 @@ distribute_notes (rtx notes, rtx from_in
NULL_RTX, NULL_RTX, NULL_RTX);
distribute_links (LOG_LINKS (cc0_setter));
+ gcc_assert (cc0_setter != last_combined_insn);
SET_INSN_DELETED (cc0_setter);
if (cc0_setter == i2)
i2 = NULL_RTX;
--- gcc/testsuite/gcc.dg/torture/pr48343.c.jj 2011-03-30 17:41:51.000000000 +0200
+++ gcc/testsuite/gcc.dg/torture/pr48343.c 2011-03-30 17:41:32.000000000 +0200
@@ -0,0 +1,19 @@
+/* PR debug/48343 */
+/* { dg-do compile } */
+/* { dg-options "-fcompare-debug" } */
+
+void foo (unsigned char *, unsigned char *);
+
+void
+test (unsigned int x, int y)
+{
+ unsigned int i, j = 0, k;
+ unsigned char s[256], t[64];
+ foo (s, t);
+ t[0] = y;
+ for (i = 0; i < 256; i++)
+ {
+ j = (j + s[i] + t[i % x]) & 0xff;
+ k = i; i = j; j = k;
+ }
+}
Jakub
More information about the Gcc-patches
mailing list