On Fri, Feb 12, 2016 at 01:50:08PM +0100, Richard Biener wrote: > > - mode1 = GET_MODE (xop1) != VOIDmode ? GET_MODE (xop1) : mode; > > - if (xmode1 != VOIDmode && xmode1 != mode1) > > + mode1 = GET_MODE (xop1); > > + if (xmode1 != mode1) > > { > > xop1 = convert_modes (xmode1, mode1, xop1, unsignedp); > > mode1 = xmode1; > > > > so if xop1 is not VOIDmode and already of xmode1 we won't do anything. > > But if it is VOIDmode (and xmode1 is not VOIDmode) we'll always > > do convert_modes. > > > > The only thing that can (hopefully not) happen is that xmode1 > > is VOIDmode but mode1 is not (maybe removing the xmode1 != VOIDmode > > check is a bit too optimistic here). Not sure if there can be > > valid patterns requesting a VOIDmode op ... (and not only accept > > CONST_INTs). > > Oh, bootstrap & testing went fine on x86_64-unknown-linux-gnu. > > If we can agree on the patch then I'll pick up the testcase from > your patch (and adjust mine).
Another possibility, only do the convert_modes from VOIDmode for shift_optab_p's xop1, and keep doing what we've done before otherwise. 2016-02-12 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/69764 PR rtl-optimization/69771 * optabs.c (expand_binop_directly): For shift_optab_p, force convert_modes with VOIDmode if xop1 has VOIDmode. * c-c++-common/pr69764.c: New test. * gcc.dg/torture/pr69771.c: New testcase. --- gcc/optabs.c.jj 2016-02-12 00:50:30.410240366 +0100 +++ gcc/optabs.c 2016-02-12 10:33:32.743492532 +0100 @@ -988,7 +988,7 @@ expand_binop_directly (machine_mode mode from_mode, 1); machine_mode xmode0 = insn_data[(int) icode].operand[1].mode; machine_mode xmode1 = insn_data[(int) icode].operand[2].mode; - machine_mode mode0, mode1, tmp_mode; + machine_mode mode0, mode1 = mode, tmp_mode; struct expand_operand ops[3]; bool commutative_p; rtx_insn *pat; @@ -1006,6 +1006,8 @@ expand_binop_directly (machine_mode mode xop0 = avoid_expensive_constant (xmode0, binoptab, 0, xop0, unsignedp); if (!shift_optab_p (binoptab)) xop1 = avoid_expensive_constant (xmode1, binoptab, 1, xop1, unsignedp); + else + mode1 = VOIDmode; /* In case the insn wants input operands in modes different from those of the actual operands, convert the operands. It would @@ -1020,7 +1020,7 @@ expand_binop_directly (machine_mode mode mode0 = xmode0; } - mode1 = GET_MODE (xop1) != VOIDmode ? GET_MODE (xop1) : mode; + mode1 = GET_MODE (xop1) != VOIDmode ? GET_MODE (xop1) : mode1; if (xmode1 != VOIDmode && xmode1 != mode1) { xop1 = convert_modes (xmode1, mode1, xop1, unsignedp); --- gcc/testsuite/c-c++-common/pr69764.c.jj 2016-02-12 10:27:34.522587995 +0100 +++ gcc/testsuite/c-c++-common/pr69764.c 2016-02-12 10:27:34.522587995 +0100 @@ -0,0 +1,38 @@ +/* PR rtl-optimization/69764 */ +/* { dg-do compile { target int32plus } } */ + +unsigned char +fn1 (unsigned char a) +{ + return a >> ~6; /* { dg-warning "right shift count is negative" } */ +} + +unsigned short +fn2 (unsigned short a) +{ + return a >> ~6; /* { dg-warning "right shift count is negative" } */ +} + +unsigned int +fn3 (unsigned int a) +{ + return a >> ~6; /* { dg-warning "right shift count is negative" } */ +} + +unsigned char +fn4 (unsigned char a) +{ + return a >> 0xff03; /* { dg-warning "right shift count >= width of type" } */ +} + +unsigned short +fn5 (unsigned short a) +{ + return a >> 0xff03; /* { dg-warning "right shift count >= width of type" } */ +} + +unsigned int +fn6 (unsigned int a) +{ + return a >> 0xff03; /* { dg-warning "right shift count >= width of type" } */ +} --- gcc/testsuite/gcc.dg/torture/pr69771.c.jj 2016-02-12 10:27:34.522587995 +0100 +++ gcc/testsuite/gcc.dg/torture/pr69771.c 2016-02-12 10:27:34.522587995 +0100 @@ -0,0 +1,12 @@ +/* PR rtl-optimization/69771 */ +/* { dg-do compile } */ + +unsigned char a = 5, c; +unsigned short b = 0; +unsigned d = 0x76543210; + +void +foo (void) +{ + c = d >> ~(a || ~b); /* { dg-warning "shift count is negative" } */ +} Jakub