Commit c7797fd3 by Segher Boessenkool Committed by Segher Boessenkool

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
parent 869032b1
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> 2019-04-14 Johannes Pfau <johannespfau@gmail.com>
* configure.ac: Remove d from unsupported languages on mingw and cygwin. * configure.ac: Remove d from unsupported languages on mingw and cygwin.
......
...@@ -2641,6 +2641,16 @@ is_just_move (rtx x) ...@@ -2641,6 +2641,16 @@ is_just_move (rtx x)
return (GET_CODE (x) == SET && general_operand (SET_SRC (x), VOIDmode)); 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. /* Try to combine the insns I0, I1 and I2 into I3.
Here I0, I1 and I2 appear earlier than 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 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, ...@@ -2706,6 +2716,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
int split_i2i3 = 0; int split_i2i3 = 0;
int changed_i3_dest = 0; int changed_i3_dest = 0;
bool i2_was_move = false, i3_was_move = false; bool i2_was_move = false, i3_was_move = false;
int n_auto_inc = 0;
int maxreg; int maxreg;
rtx_insn *temp_insn; rtx_insn *temp_insn;
...@@ -3210,6 +3221,16 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, ...@@ -3210,6 +3221,16 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
return 0; 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 /* 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), so that when we substitute I1SRC for I1DEST in
PATTERN (I2), we are only substituting for the original I1DEST, not into 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, ...@@ -3411,18 +3432,11 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
if (i1 && GET_CODE (newpat) != CLOBBER) if (i1 && GET_CODE (newpat) != CLOBBER)
{ {
/* Check that an autoincrement side-effect on I1 has not been lost. /* Before we can do this substitution, we must redo the test done
This happens if I1DEST is mentioned in I2 and dies there, and above (see detailed comments there) that ensures I1DEST isn't
has disappeared from the new pattern. */ mentioned in any SETs in NEWPAT that are field assignments. */
if ((FIND_REG_INC_NOTE (i1, NULL_RTX) != 0 if (!combinable_i3pat (NULL, &newpat, i1dest, NULL_RTX, NULL_RTX,
&& i1_feeds_i2_n 0, 0, 0))
&& 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))
{ {
undo_all (); undo_all ();
return 0; return 0;
...@@ -3452,12 +3466,8 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, ...@@ -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 (i0 && GET_CODE (newpat) != CLOBBER)
{ {
if ((FIND_REG_INC_NOTE (i0, NULL_RTX) != 0 if (!combinable_i3pat (NULL, &newpat, i0dest, NULL_RTX, NULL_RTX,
&& ((i0_feeds_i2_n && dead_or_set_p (i2, i0dest)) 0, 0, 0))
|| (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))
{ {
undo_all (); undo_all ();
return 0; return 0;
...@@ -3478,6 +3488,20 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, ...@@ -3478,6 +3488,20 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0,
substed_i0 = 1; 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 /* Fail if an autoincrement side-effect has been duplicated. Be careful
to count all the ways that I2SRC and I1SRC can be used. */ to count all the ways that I2SRC and I1SRC can be used. */
if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0 if ((FIND_REG_INC_NOTE (i2, NULL_RTX) != 0
......
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> 2019-04-15 Richard Biener <rguenther@suse.de>
PR ipa/88936 PR ipa/88936
......
/* { 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;
}
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