re PR rtl-optimization/67028 (combine bug. Different assumptions about subreg in different places.)

PR rtl-optimization/67028
	* combine.c (simplify_comparison): Fix comment.  Rearrange code.
	Add test to see if a const_int fits in the new mode.

gcc/testsuite/
	PR rtl-optimization/67028
	* gcc.dg/pr67028.c: New testcase.

From-SVN: r226731
This commit is contained in:
Segher Boessenkool 2015-08-08 03:51:27 +02:00 committed by Segher Boessenkool
parent 0fa95f4ead
commit 1aeec6dc1f
4 changed files with 44 additions and 7 deletions

View File

@ -1,3 +1,9 @@
2015-08-08 Segher Boessenkool <segher@kernel.crashing.org>
PR rtl-optimization/67028
* combine.c (simplify_comparison): Fix comment. Rearrange code.
Add test to see if a const_int fits in the new mode.
2015-08-07 DJ Delorie <dj@redhat.com>
* config/rx/rx.c (rx_mode_dependent_address_p): Remove unneeded asserts.

View File

@ -12057,14 +12057,15 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
continue;
}
/* If this is (and:M1 (subreg:M2 X 0) (const_int C1)) where C1
/* If this is (and:M1 (subreg:M1 X:M2 0) (const_int C1)) where C1
fits in both M1 and M2 and the SUBREG is either paradoxical
or represents the low part, permute the SUBREG and the AND
and try again. */
if (GET_CODE (XEXP (op0, 0)) == SUBREG)
if (GET_CODE (XEXP (op0, 0)) == SUBREG
&& CONST_INT_P (XEXP (op0, 1)))
{
unsigned HOST_WIDE_INT c1;
tmode = GET_MODE (SUBREG_REG (XEXP (op0, 0)));
unsigned HOST_WIDE_INT c1 = INTVAL (XEXP (op0, 1));
/* Require an integral mode, to avoid creating something like
(AND:SF ...). */
if (SCALAR_INT_MODE_P (tmode)
@ -12074,16 +12075,20 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
have a defined value due to the AND operation.
However, if we commute the AND inside the SUBREG then
they no longer have defined values and the meaning of
the code has been changed. */
the code has been changed.
Also C1 should not change value in the smaller mode,
see PR67028 (a positive C1 can become negative in the
smaller mode, so that the AND does no longer mask the
upper bits). */
&& ((WORD_REGISTER_OPERATIONS
&& mode_width > GET_MODE_PRECISION (tmode)
&& mode_width <= BITS_PER_WORD)
&& mode_width <= BITS_PER_WORD
&& trunc_int_for_mode (c1, tmode) == (HOST_WIDE_INT) c1)
|| (mode_width <= GET_MODE_PRECISION (tmode)
&& subreg_lowpart_p (XEXP (op0, 0))))
&& CONST_INT_P (XEXP (op0, 1))
&& mode_width <= HOST_BITS_PER_WIDE_INT
&& HWI_COMPUTABLE_MODE_P (tmode)
&& ((c1 = INTVAL (XEXP (op0, 1))) & ~mask) == 0
&& (c1 & ~mask) == 0
&& (c1 & ~GET_MODE_MASK (tmode)) == 0
&& c1 != mask
&& c1 != GET_MODE_MASK (tmode))

View File

@ -1,3 +1,8 @@
2015-08-08 Segher Boessenkool <segher@kernel.crashing.org>
PR rtl-optimization/67028
* gcc.dg/pr67028.c: New testcase.
2015-08-07 H.J. Lu <hongjiu.lu@intel.com>
PR rtl-optimization/67029

View File

@ -0,0 +1,21 @@
/* { dg-do run } */
/* { dg-options "-O3" } */
short c = 0;
int __attribute__ ((noinline)) f(void)
{
int d = 5;
signed char e = (c != 1) * -2;
int a = (unsigned short)e > d;
return a;
}
int main(void)
{
if (!f())
__builtin_abort();
return 0;
}