Commit b92977ee by Alexandre Oliva Committed by Alexandre Oliva

[PR80693] drop value of parallel SETs dropped by combine

When combine drops a REG_UNUSED SET in a parallel, we have to clear
cached values, so that, even if the REGs remain used (e.g. because
they were referenced in the used SET_SRC), we will not use properties
of the dropped modified value as if they applied to the preserved
original one.

We fail to adjust REG_N_SETS.

for  gcc/ChangeLog

	PR rtl-optimization/80693
	PR rtl-optimization/81019
	PR rtl-optimization/81020
	* combine.c (distribute_notes): Reset any REG_UNUSED REGs that
	are not mentioned in i3.  Place the REG_UNUSED note on i2,
	possibly modified to REG_DEAD, if it did not originate in i3.

for  gcc/testsuite/ChangeLog

	PR rtl-optimization/80693
	PR rtl-optimization/81019
	PR rtl-optimization/81020
	* gcc.dg/pr80693.c: New.
	* gcc.dg/pr81019.c: New.

From-SVN: r255554
parent 0a2c5149
2017-12-11 Alexandre Oliva <aoliva@redhat.com>
PR rtl-optimization/80693
PR rtl-optimization/81019
PR rtl-optimization/81020
* combine.c (distribute_notes): Reset any REG_UNUSED REGs that
are not mentioned in i3. Place the REG_UNUSED note on i2,
possibly modified to REG_DEAD, if it did not originate in i3.
2017-12-11 Jakub Jelinek <jakub@redhat.com> 2017-12-11 Jakub Jelinek <jakub@redhat.com>
* recog.c (store_data_bypass_p_1): New function. * recog.c (store_data_bypass_p_1): New function.
...@@ -14219,6 +14219,46 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2, ...@@ -14219,6 +14219,46 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
PUT_REG_NOTE_KIND (note, REG_DEAD); PUT_REG_NOTE_KIND (note, REG_DEAD);
place = i3; place = i3;
} }
/* A SET or CLOBBER of the REG_UNUSED reg has been removed,
but we can't tell which at this point. We must reset any
expectations we had about the value that was previously
stored in the reg. ??? Ideally, we'd adjust REG_N_SETS
and, if appropriate, restore its previous value, but we
don't have enough information for that at this point. */
else
{
record_value_for_reg (XEXP (note, 0), NULL, NULL_RTX);
/* Otherwise, if this register is now referenced in i2
then the register used to be modified in one of the
original insns. If it was i3 (say, in an unused
parallel), it's now completely gone, so the note can
be discarded. But if it was modified in i2, i1 or i0
and we still reference it in i2, then we're
referencing the previous value, and since the
register was modified and REG_UNUSED, we know that
the previous value is now dead. So, if we only
reference the register in i2, we change the note to
REG_DEAD, to reflect the previous value. However, if
we're also setting or clobbering the register as
scratch, we know (because the register was not
referenced in i3) that it's unused, just as it was
unused before, and we place the note in i2. */
if (from_insn != i3 && i2 && INSN_P (i2)
&& reg_referenced_p (XEXP (note, 0), PATTERN (i2)))
{
if (!reg_set_p (XEXP (note, 0), PATTERN (i2)))
PUT_REG_NOTE_KIND (note, REG_DEAD);
if (! (REG_P (XEXP (note, 0))
? find_regno_note (i2, REG_NOTE_KIND (note),
REGNO (XEXP (note, 0)))
: find_reg_note (i2, REG_NOTE_KIND (note),
XEXP (note, 0))))
place = i2;
}
}
break; break;
case REG_EQUAL: case REG_EQUAL:
......
2017-12-11 Alexandre Oliva <aoliva@redhat.com>
PR rtl-optimization/80693
PR rtl-optimization/81019
PR rtl-optimization/81020
* gcc.dg/pr80693.c: New.
* gcc.dg/pr81019.c: New.
2017-12-11 Segher Boessenkool <segher@kernel.crashing.org> 2017-12-11 Segher Boessenkool <segher@kernel.crashing.org>
PR rtl-optimization/83361 PR rtl-optimization/83361
......
/* { dg-do run } */
/* { dg-options "-O -fno-tree-coalesce-vars" } */
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned u32;
typedef unsigned long long u64;
static u64 __attribute__((noinline, noclone))
foo(u8 u8_0, u16 u16_0, u32 u32_0, u64 u64_0, u16 u16_1)
{
u16_1 += 0x1051;
u16_1 &= 1;
u8_0 <<= u32_0 & 7;
u16_0 -= !u16_1;
u16_1 >>= ((u16)-u8_0 != 0xff);
return u8_0 + u16_0 + u64_0 + u16_1;
}
int
main (void)
{
u64 x = foo(1, 1, 0xffff, 0, 1);
if (x != 0x80)
__builtin_abort();
return 0;
}
/* PR rtl-optimization/81019 */
/* { dg-do run } */
/* { dg-options "-O -fno-tree-ccp" } */
unsigned long long __attribute__((noinline, noclone))
foo (unsigned char a, unsigned short b, unsigned c, unsigned long long d,
unsigned char e, unsigned short f, unsigned g, unsigned long long h)
{
g = e;
c &= 0 < d;
b *= d;
g ^= -1;
g &= 1;
c |= 1;
a -= 0 < g;
g >>= 1;
f = b | (f >> b);
return a + c + d + f + g + h;
}
int
main (void)
{
if (foo (0, 0, 0, 0, 0, 0, 0, 0) != 0x100)
__builtin_abort ();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment