On Wed, Nov 09, 2011 at 04:44:55PM +0100, Bernd Schmidt wrote: > On 11/09/11 16:32, Jakub Jelinek wrote: > > --- gcc/combine.c.jj 2011-11-08 23:35:12.000000000 +0100 > > +++ gcc/combine.c 2011-11-09 10:06:27.207333364 +0100 > > @@ -11397,9 +11397,12 @@ simplify_comparison (enum rtx_code code, > > later on, and then we wouldn't know whether to sign- or > > zero-extend. */ > > mode = GET_MODE (XEXP (op0, 0)); > > - if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT > > + if (GET_MODE_CLASS (mode) == MODE_INT > > && ! unsigned_comparison_p > > - && val_signbit_known_clear_p (mode, const_op) > > + && HWI_COMPUTABLE_MODE_P (mode) > > + && ((unsigned HOST_WIDE_INT) const_op > > + < (((unsigned HOST_WIDE_INT) 1 > > + << (GET_MODE_PRECISION (mode) - 1)))) > > && have_insn_for (COMPARE, mode)) > > { > > op0 = XEXP (op0, 0); > > I guess this is OK, although it would still be nicer to use something > with a descriptive name rather than bit-fiddling, to avoid this kind of > confusion. Maybe check whether trunc_int_for_mode doesn't change the > constant? Or we could make val_signbit_known_clear_p do more extensive > checking.
Do you think this is more readable? That matches what the old code did, though I wonder if the c >= 0 test is needed there at all and if simply && trunc_int_for_mode (const_op, mode) == const_op couldn't be used and handle also negative constants - the comparison is signed and the other operand is sign extended... 2011-11-09 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/51023 * combine.c (simplify_comparison) <case SIGN_EXTEND>: Don't use val_signbit_known_clear_p for signed comparison narrowing optimization. Don't check for non-VOIDmode, use HWI_COMPUTABLE_MODE_P macro. <case ZERO_EXTEND>: Don't check for non-VOIDmode. * gcc.c-torture/execute/pr51023.c: New test. --- gcc/combine.c.jj 2011-11-08 23:35:12.000000000 +0100 +++ gcc/combine.c 2011-11-09 10:06:27.207333364 +0100 @@ -11397,13 +11397,20 @@ simplify_comparison (enum rtx_code code, later on, and then we wouldn't know whether to sign- or zero-extend. */ mode = GET_MODE (XEXP (op0, 0)); - if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT + if (GET_MODE_CLASS (mode) == MODE_INT && ! unsigned_comparison_p - && val_signbit_known_clear_p (mode, const_op) - && have_insn_for (COMPARE, mode)) + && HWI_COMPUTABLE_MODE_P (mode)) { - op0 = XEXP (op0, 0); - continue; + HOST_WIDE_INT c = trunc_int_for_mode (const_op, mode); + /* Don't do this if the sign bit of MODE or any + higher bit is set in CONST_OP. */ + if (c == const_op + && c >= 0 + && have_insn_for (COMPARE, mode)) + { + op0 = XEXP (op0, 0); + continue; + } } break; @@ -11477,7 +11484,7 @@ simplify_comparison (enum rtx_code code, case ZERO_EXTEND: mode = GET_MODE (XEXP (op0, 0)); - if (mode != VOIDmode && GET_MODE_CLASS (mode) == MODE_INT + if (GET_MODE_CLASS (mode) == MODE_INT && (unsigned_comparison_p || equality_comparison_p) && HWI_COMPUTABLE_MODE_P (mode) && ((unsigned HOST_WIDE_INT) const_op < GET_MODE_MASK (mode)) --- gcc/testsuite/gcc.c-torture/execute/pr51023.c.jj 2011-11-09 10:17:31.133406427 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr51023.c 2011-11-09 10:17:13.000000000 +0100 @@ -0,0 +1,18 @@ +/* PR rtl-optimization/51023 */ + +extern void abort (void); + +short int +foo (long int x) +{ + return x; +} + +int +main () +{ + long int a = 0x4272AL; + if (foo (a) == a) + abort (); + return 0; +} Jakub