Hi! In July Richard changed reduce_bit_field BIT_NOT_EXPR expansion from NOT unop to XOR with all the bits in the bitfield's precision set. Unfortunately that is correct for unsigned bitfields only, for signed bitfields, where op0 is already sign-extended to its mode before this, expanding this as NOT is the right thing.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2012-02-11 Jakub Jelinek <ja...@redhat.com> PR middle-end/52209 * expr.c (expand_expr_real_2) <case BIT_NOT_EXPR>: Only expand using XOR for reduce_bit_field if type is unsigned. * gcc.c-torture/execute/pr52209.c: New test. --- gcc/expr.c.jj 2012-02-07 16:05:51.000000000 +0100 +++ gcc/expr.c 2012-02-11 10:08:44.162924423 +0100 @@ -8582,8 +8582,9 @@ expand_expr_real_2 (sepops ops, rtx targ if (modifier == EXPAND_STACK_PARM) target = 0; /* In case we have to reduce the result to bitfield precision - expand this as XOR with a proper constant instead. */ - if (reduce_bit_field) + for unsigned bitfield expand this as XOR with a proper constant + instead. */ + if (reduce_bit_field && TYPE_UNSIGNED (type)) temp = expand_binop (mode, xor_optab, op0, immed_double_int_const (double_int_mask (TYPE_PRECISION (type)), mode), --- gcc/testsuite/gcc.c-torture/execute/pr52209.c.jj 2012-02-11 10:09:46.080571803 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr52209.c 2012-02-11 10:09:28.000000000 +0100 @@ -0,0 +1,14 @@ +/* PR middle-end/52209 */ + +extern void abort (void); +struct S0 { int f2 : 1; } c; +int b; + +int +main () +{ + b = -1 ^ c.f2; + if (b != -1) + abort (); + return 0; +} Jakub