combine: Count auto_inc properly (PR89794)

The code that checks if an auto-increment from i0 or i1 is not lost is
a bit shaky.  The code to check the same for i2 is non-existent, and
cannot be implemented in a similar way at all.  So, this patch counts
all auto-increments, and makes sure we end up with the same number as
we started with.  This works because we still have a check that we
will not duplicate any.

We should do this some better way, but not while we are in stage 4.


	PR rtl-optimization/89794
	* combine.c (count_auto_inc): New function.
	(try_combine): Count how many auto_inc expressions there were in the
	original instructions.  Ensure we have the same number in the new
	instructions.  Remove the code that tried to ensure auto_inc side
	effects on i1 and i0 are not lost.

gcc/testsuite/
	PR rtl-optimization/89794
	* gcc.dg/torture/pr89794.c: New testcase.

From-SVN: r270368
This commit is contained in:
Segher Boessenkool 2019-04-15 13:33:29 +02:00 committed by Segher Boessenkool
parent 869032b176
commit c7797fd3e8
4 changed files with 80 additions and 18 deletions

View File

@ -1,3 +1,12 @@
2019-04-15 Segher Boessenkool <segher@kernel.crashing.org>
PR rtl-optimization/89794
* combine.c (count_auto_inc): New function.
(try_combine): Count how many auto_inc expressions there were in the
original instructions. Ensure we have the same number in the new
instructions. Remove the code that tried to ensure auto_inc side
effects on i1 and i0 are not lost.
2019-04-14 Johannes Pfau <johannespfau@gmail.com>
* configure.ac: Remove d from unsupported languages on mingw and cygwin.

View File

@ -2641,6 +2641,16 @@ is_just_move (rtx x)
return (GET_CODE (x) == SET && general_operand (SET_SRC (x), VOIDmode));
}
/* Callback function to count autoincs. */
static int
count_auto_inc (rtx, rtx, rtx, rtx, rtx, void *arg)
{
(*((int *) arg))++;
return 0;
}
/* Try to combine the insns I0, I1 and I2 into I3.
Here I0, I1 and I2 appear earlier than I3.
I0 and I1 can be zero; then we combine just I2 into I3, or I1 and I2 into
@ -2706,6 +2716,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
int split_i2i3 = 0;
int changed_i3_dest = 0;
bool i2_was_move = false, i3_was_move = false;
int n_auto_inc = 0;
int maxreg;
rtx_insn *temp_insn;
@ -3210,6 +3221,16 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
return 0;
}
/* Count how many auto_inc expressions there were in the original insns;
we need to have the same number in the resulting patterns. */
if (i0)
for_each_inc_dec (PATTERN (i0), count_auto_inc, &n_auto_inc);
if (i1)
for_each_inc_dec (PATTERN (i1), count_auto_inc, &n_auto_inc);
for_each_inc_dec (PATTERN (i2), count_auto_inc, &n_auto_inc);
for_each_inc_dec (PATTERN (i3), count_auto_inc, &n_auto_inc);
/* If the set in I2 needs to be kept around, we must make a copy of
PATTERN (I2), so that when we substitute I1SRC for I1DEST in
PATTERN (I2), we are only substituting for the original I1DEST, not into
@ -3411,18 +3432,11 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
if (i1 && GET_CODE (newpat) != CLOBBER)
{
/* Check that an autoincrement side-effect on I1 has not been lost.
This happens if I1DEST is mentioned in I2 and dies there, and
has disappeared from the new pattern. */
if ((FIND_REG_INC_NOTE (i1, NULL_RTX) != 0
&& i1_feeds_i2_n
&& dead_or_set_p (i2, i1dest)
&& !reg_overlap_mentioned_p (i1dest, newpat))
/* Before we can do this substitution, we must redo the test done
above (see detailed comments there) that ensures I1DEST isn't
mentioned in any SETs in NEWPAT that are field assignments. */
|| !combinable_i3pat (NULL, &newpat, i1dest, NULL_RTX, NULL_RTX,
0, 0, 0))
/* Before we can do this substitution, we must redo the test done
above (see detailed comments there) that ensures I1DEST isn't
mentioned in any SETs in NEWPAT that are field assignments. */
if (!combinable_i3pat (NULL, &newpat, i1dest, NULL_RTX, NULL_RTX,
0, 0, 0))
{
undo_all ();
return 0;
@ -3452,12 +3466,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
if (i0 && GET_CODE (newpat) != CLOBBER)
{
if ((FIND_REG_INC_NOTE (i0, NULL_RTX) != 0
&& ((i0_feeds_i2_n && dead_or_set_p (i2, i0dest))
|| (i0_feeds_i1_n && dead_or_set_p (i1, i0dest)))
&& !reg_overlap_mentioned_p (i0dest, newpat))
|| !combinable_i3pat (NULL, &newpat, i0dest, NULL_RTX, NULL_RTX,
0, 0, 0))
if (!combinable_i3pat (NULL, &newpat, i0dest, NULL_RTX, NULL_RTX,
0, 0, 0))
{
undo_all ();
return 0;
@ -3478,6 +3488,20 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
substed_i0 = 1;
}
if (n_auto_inc)
{
int new_n_auto_inc = 0;
for_each_inc_dec (newpat, count_auto_inc, &new_n_auto_inc);
if (n_auto_inc != new_n_auto_inc)
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Number of auto_inc expressions changed\n");
undo_all ();
return 0;
}
}
/* Fail if an autoincrement side-effect has been duplicated. Be careful
to count all the ways that I2SRC and I1SRC can be used. */
if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0

View File

@ -1,3 +1,8 @@
2019-04-15 Segher Boessenkool <segher@kernel.crashing.org>
PR rtl-optimization/89794
* gcc.dg/torture/pr89794.c: New testcase.
2019-04-15 Richard Biener <rguenther@suse.de>
PR ipa/88936

View File

@ -0,0 +1,24 @@
/* { dg-do run } */
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
u32 a, b, c, d;
u32 foo (u32 f, u32 g, u32 g2, u32 g3, u16 h, u16 i)
{
(void)g, (void)g2, (void)g3, (void)h;
d = __builtin_bswap64 (i);
__builtin_sub_overflow (0, d, &b);
__builtin_memset (&i, c, 2);
a = 0;
return b + f + i + c;
}
int main (void)
{
u32 x = foo (0, 0, 0, 0, 0, 0);
asm ("" :: "r" (x));
return 0;
}