From: Richard Biener Date: Tue, 6 Nov 2018 08:09:03 +0000 (+0000) Subject: re PR middle-end/18041 (OR of two single-bit bitfields is inefficient) X-Git-Tag: basepoints/gcc-10~3296 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ffe5a586ccb5805010b933d4be1d238c895c3409;p=thirdparty%2Fgcc.git re PR middle-end/18041 (OR of two single-bit bitfields is inefficient) 2018-11-06 Richard Biener PR middle-end/18041 * simplify-rtx.c (simplify_binary_operation_1): Add pattern matching bitfield insertion. * gcc.target/i386/pr18041-1.c: New testcase. * gcc.target/i386/pr18041-2.c: Likewise. From-SVN: r265829 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2c5abd39a4ba..b4b36e0b5704 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2018-11-06 Richard Biener + + PR middle-end/18041 + * simplify-rtx.c (simplify_binary_operation_1): Add pattern + matching bitfield insertion. + 2018-11-06 Alexandre Oliva * auto-inc-dec.c: Include valtrack.h. Improve comments. diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 2ff68ceb4e33..0d53135f1ff8 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -2857,6 +2857,38 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, XEXP (op0, 1)); } + /* The following happens with bitfield merging. + (X & C) | ((X | Y) & ~C) -> X | (Y & ~C) */ + if (GET_CODE (op0) == AND + && GET_CODE (op1) == AND + && CONST_INT_P (XEXP (op0, 1)) + && CONST_INT_P (XEXP (op1, 1)) + && (INTVAL (XEXP (op0, 1)) + == ~INTVAL (XEXP (op1, 1)))) + { + /* The IOR may be on both sides. */ + rtx top0 = NULL_RTX, top1 = NULL_RTX; + if (GET_CODE (XEXP (op1, 0)) == IOR) + top0 = op0, top1 = op1; + else if (GET_CODE (XEXP (op0, 0)) == IOR) + top0 = op1, top1 = op0; + if (top0 && top1) + { + /* X may be on either side of the inner IOR. */ + rtx tem = NULL_RTX; + if (rtx_equal_p (XEXP (top0, 0), + XEXP (XEXP (top1, 0), 0))) + tem = XEXP (XEXP (top1, 0), 1); + else if (rtx_equal_p (XEXP (top0, 0), + XEXP (XEXP (top1, 0), 1))) + tem = XEXP (XEXP (top1, 0), 0); + if (tem) + return simplify_gen_binary (IOR, mode, XEXP (top0, 0), + simplify_gen_binary + (AND, mode, tem, XEXP (top1, 1))); + } + } + tem = simplify_byte_swapping_operation (code, mode, op0, op1); if (tem) return tem; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 061fa46eba24..0bfb80f468bf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2018-11-06 Richard Biener + + PR middle-end/18041 + * gcc.target/i386/pr18041-1.c: New testcase. + * gcc.target/i386/pr18041-2.c: Likewise. + 2018-11-06 Wei Xiao * gcc.target/i386/avx-1.c: Update tests for VFIXUPIMM* intrinsics. diff --git a/gcc/testsuite/gcc.target/i386/pr18041-1.c b/gcc/testsuite/gcc.target/i386/pr18041-1.c new file mode 100644 index 000000000000..24da41a02ec9 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr18041-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +struct B { unsigned bit0 : 1; unsigned bit1 : 1; }; + +void +foo (struct B *b) +{ + b->bit0 = b->bit0 | b->bit1; +} + +/* { dg-final { scan-assembler-times "and" 1 } } */ +/* { dg-final { scan-assembler-times "or" 1 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr18041-2.c b/gcc/testsuite/gcc.target/i386/pr18041-2.c new file mode 100644 index 000000000000..00ebd2ae36d5 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr18041-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +struct B { unsigned bit0 : 1; unsigned bit1 : 1; }; + +void +bar (struct B *b, int x) +{ + b->bit0 |= x; +} + +/* This fails to combine in 32bit mode but not for x32. */ +/* { dg-final { scan-assembler-times "and" 1 { xfail { { ! x32 } && ilp32 } } } } */ +/* { dg-final { scan-assembler-times "or" 1 { xfail { { ! x32 } && ilp32 } } } } */