[PATCH] Fix BIT_NOT_EXPR expansion with bitfields
Richard Guenther
rguenther@suse.de
Mon Jul 18 13:14:00 GMT 2011
We currently fail to handle bitfield precision BIT_NOT_EXPRs properly
and miscompile the testcase below. Fixed by properly truncating to
bitfield precision if required. Do that by expanding the NOT to
a proper XOR instead of doing the truncation via a AND though.
Bootstrap and regtest pending on x86_64-unknown-linux-gnu.
Richard.
2011-07-18 Richard Guenther <rguenther@suse.de>
* expr.c (expand_expr_real_2): Properly truncate the BIT_NOT_EXPR
expansion result to bitfield precision if required.
* gcc.dg/torture/20110718-1.c: New testcase.
Index: gcc/expr.c
===================================================================
--- gcc/expr.c (revision 176386)
+++ gcc/expr.c (working copy)
@@ -8037,7 +8037,15 @@ expand_expr_real_2 (sepops ops, rtx targ
VOIDmode, EXPAND_NORMAL);
if (modifier == EXPAND_STACK_PARM)
target = 0;
- temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
+ /* In case we have to reduce the result to bitfield precision
+ expand this as XOR with a proper constant instead. */
+ if (reduce_bit_field)
+ temp = expand_binop (mode, xor_optab, op0,
+ immed_double_int_const
+ (double_int_mask (TYPE_PRECISION (type)), mode),
+ target, 1, OPTAB_LIB_WIDEN);
+ else
+ temp = expand_unop (mode, one_cmpl_optab, op0, target, 1);
gcc_assert (temp);
return temp;
Index: gcc/testsuite/gcc.dg/torture/20110718-1.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/20110718-1.c (revision 0)
+++ gcc/testsuite/gcc.dg/torture/20110718-1.c (revision 0)
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+
+extern void abort (void);
+struct X { unsigned long i : 33; };
+unsigned long __attribute__((noinline))
+foo (struct X *p)
+{
+ return ~p->i;
+}
+int main()
+{
+ struct X x;
+ x.i = -1;
+ if (foo (&x) != 0)
+ abort ();
+ return 0;
+}
More information about the Gcc-patches
mailing list