On Tue, Mar 15, 2016 at 01:08:50PM +0100, Bernd Schmidt wrote: > This looks really specialized, and I'd be worrying about whether it really > is the right condition. Where exactly was the constant shifted by 31 and > count set to 0? Must be here, right?
Yes, it is that spot. > > /* If we have (A << B << C) for any shift, we can convert this to > (A << C << B). This wins if A is a constant. Only try this if > B is not a constant. */ > > else if (GET_CODE (varop) == code > && CONST_INT_P (XEXP (varop, 0)) > && !CONST_INT_P (XEXP (varop, 1))) > { > rtx new_rtx = simplify_const_binary_operation (code, mode, > XEXP (varop, 0), > GEN_INT (count)); > varop = gen_rtx_fmt_ee (code, mode, new_rtx, XEXP (varop, 1)); > count = 0; > continue; > } > > I think it might be clearer to notice and fix the problem here (or set a > need_mask flag). So do you prefer this instead? 2016-03-15 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/70222 * combine.c (simplify_shift_const_1): For A >> B >> C LSHIFTRT optimization if mode is different from result_mode, queue up masking of the result in outer_op. Formatting fix. * gcc.c-torture/execute/pr70222-1.c: New test. * gcc.c-torture/execute/pr70222-2.c: New test. --- gcc/combine.c.jj 2016-03-14 23:18:37.958408627 +0100 +++ gcc/combine.c 2016-03-15 14:08:34.754434506 +0100 @@ -10524,9 +10524,19 @@ simplify_shift_const_1 (enum rtx_code co && CONST_INT_P (XEXP (varop, 0)) && !CONST_INT_P (XEXP (varop, 1))) { + /* For ((unsigned) (cstULL >> count)) >> cst2 we have to make + sure the result will be masked. See PR70222. */ + if (code == LSHIFTRT + && mode != result_mode + && !merge_outer_ops (&outer_op, &outer_const, AND, + GET_MODE_MASK (result_mode) + >> orig_count, result_mode, + &complement_p)) + break; + rtx new_rtx = simplify_const_binary_operation (code, mode, - XEXP (varop, 0), - GEN_INT (count)); + XEXP (varop, 0), + GEN_INT (count)); varop = gen_rtx_fmt_ee (code, mode, new_rtx, XEXP (varop, 1)); count = 0; continue; --- gcc/testsuite/gcc.c-torture/execute/pr70222-1.c.jj 2016-03-15 11:30:41.657000384 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr70222-1.c 2016-03-15 11:30:41.657000384 +0100 @@ -0,0 +1,30 @@ +/* PR rtl-optimization/70222 */ + +int a = 1; +unsigned int b = 2; +int c = 0; +int d = 0; + +void +foo () +{ + int e = ((-(c >= c)) < b) > ((int) (-1ULL >> ((a / a) * 15))); + d = -e; +} + +__attribute__((noinline, noclone)) void +bar (int x) +{ + if (x != -1) + __builtin_abort (); +} + +int +main () +{ +#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 + foo (); + bar (d); +#endif + return 0; +} --- gcc/testsuite/gcc.c-torture/execute/pr70222-2.c.jj 2016-03-15 11:36:13.273366841 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr70222-2.c 2016-03-15 11:36:18.156298614 +0100 @@ -0,0 +1,20 @@ +/* PR rtl-optimization/70222 */ + +#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 +__attribute__((noinline, noclone)) unsigned int +foo (int x) +{ + unsigned long long y = -1ULL >> x; + return (unsigned int) y >> 31; +} +#endif + +int +main () +{ +#if __CHAR_BIT__ == 8 && __SIZEOF_INT__ == 4 && __SIZEOF_LONG_LONG__ == 8 + if (foo (15) != 1 || foo (32) != 1 || foo (33) != 0) + __builtin_abort (); +#endif + return 0; +} Jakub