The attached file generates ideal code, a test of a single bit, for the condition in test_pic or test_exe depending on -DALT. gcc ought to be able to optimise to a single bit test for both functions whether or not -DALT. It looks like gcc incorrectly prefers a range test.
Created attachment 36247 [details] testcase from binutils/include/bfdlink.h
Note this is already fold-const.c:optimize_bit_field_compare at work. With -DALT (non-working code) we get ;; Function test_pic (null) ;; enabled by -tree-original { if ((BIT_FIELD_REF <*info, 8, 0> & 3) + 254 <= 1) and ;; Function test_exe (null) ;; enabled by -tree-original { if ((SAVE_EXPR <BIT_FIELD_REF <*info, 8, 0> & 3>) == 0 || (SAVE_EXPR <BIT_FIELD_REF <*info, 8, 0> & 3>) == 2) from it. Without -DALT ;; Function test_pic (null) ;; enabled by -tree-original { if ((SAVE_EXPR <BIT_FIELD_REF <*info, 8, 0> & 3>) == 3 || (SAVE_EXPR <BIT_FIELD_REF <*info, 8, 0> & 3>) == 1) ;; Function test_exe (null) ;; enabled by -tree-original { if ((BIT_FIELD_REF <*info, 8, 0> & 3) <= 1) I see more that a single bit test for both cases btw, mostly because we need to mask the padding. Not sure what optimal code you expect here.
Maybe adding #if ALT only confused the issue. For -UALT -O1 on x86_64 I get test_pic: testb $1, (%rdi) je .L1 addl $1, result(%rip) .L1: rep ret test_exe: movzbl (%rdi), %eax andl $3, %eax cmpb $1, %al ja .L3 addl $1, result(%rip) .L3: rep ret For test_exe I would like to see the following equivalent and better optimised code. test_exe: testb $2, (%rdi) jne .L3 addl $1, result(%rip) .L3: rep ret The optimisation to a bit test for test_pic happens in reassoc1, or at least that's where the process starts.
Proposed patch in https://gcc.gnu.org/ml/gcc-patches/2017-01/msg01936.html
PR 67731 maybe related or dup?
(In reply to Oleg Endo from comment #5) > PR 67731 maybe related or dup? Related but not a dup. This bug is caused by frontend folding two bitfield accesses to a single comparison which prevented generation of bit test later in tree-opt.
Author: chefmax Date: Tue Jun 13 11:13:52 2017 New Revision: 249149 URL: https://gcc.gnu.org/viewcvs?rev=249149&root=gcc&view=rev Log: 2017-06-13 Yury Gribov <tetra2005@gmail.com> gcc/ PR tree-optimization/67328 * fold-const.c (maskable_range_p): New function. (build_range_check): Generate bittests if possible. gcc/testsuite/ PR tree-optimization/67328 * c-c++-common/fold-masked-cmp-1.c: New test. * c-c++-common/fold-masked-cmp-2.c: Likewise. * gcc.dg/pr46309.c: Fix pattern. * gcc.dg/pr46309-2.c: Likewise. Added: trunk/gcc/testsuite/c-c++-common/fold-masked-cmp-1.c trunk/gcc/testsuite/c-c++-common/fold-masked-cmp-2.c Modified: trunk/gcc/ChangeLog trunk/gcc/fold-const.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.dg/pr46309-2.c trunk/gcc/testsuite/gcc.dg/pr46309.c
Alan,(In reply to Alan Modra from comment #0) > It looks like gcc incorrectly prefers a range test. Alan, can we close this?
Thanks for the fix!