This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Committed] Use fold in optimize_bit_field_compare
- From: Roger Sayle <roger at eyesopen dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 13 Nov 2006 15:18:38 -0700 (MST)
- Subject: [Committed] Use fold in optimize_bit_field_compare
Many thanks to Steven Bosscher for asking exactly how much my recent
fix for PR13827 affected the GCC's own bit-field comparisons. My first
thought was that with tree-ssa, we preserve the bitfields and that this
optimization was already done during RTL expansion. Turns out that I
was mistaken and that we do expose "(X&C) == (Y&C)" to the tree-ssa
optimizers. Unfortunately, when optimize_bit_field_compare currently
generates these trees, it uses the deprecated build2 interfaces rather
than the newer fold_build2, so we don't get to benefit from this new
optimization. Doh!
Fixed with the obvious patch below...
Consider the example code below:
typedef struct {
unsigned prefix : 4;
unsigned code : 4;
unsigned unsigned_p : 4;
} tree_common;
int foo(tree_common *a, tree_common *b)
{
return a->code == b->code;
}
Previously on x86, with -O2 -fomit-frame-pointer we'd generate:
foo: movl 4(%esp), %eax
movzbl (%eax), %edx
movl 8(%esp), %eax
andl $-16, %edx
movzbl (%eax), %eax
andl $-16, %eax
cmpb %al, %dl
sete %al
movzbl %al, %eax
ret
but with the patch below we now generate:
foo: movl 4(%esp), %eax
movl 8(%esp), %edx
movzbl (%eax), %eax
xorb (%edx), %al
testb $-16, %al
sete %al
movzbl %al, %eax
ret
Which is certainly smaller (22 bytes vs. 29) and probably always faster.
This patch has been tested on i686-pc-linux-gnu with a full "make
bootstrap", all default languages including Ada, and regression tested
with a top-level "make -k check" with no new failures.
Committed to mainline as revision 118783.
2006-11-13 Roger Sayle <roger@eyesopen.com>
* fold-const.c (optimize_bit_field_compare): Recursively call
fold when simplifying non-constant comparisons between bit-fields.
Index: fold-const.c
===================================================================
*** fold-const.c (revision 118727)
--- fold-const.c (working copy)
*************** optimize_bit_field_compare (enum tree_co
*** 3427,3441 ****
if (! const_p)
/* If not comparing with constant, just rework the comparison
and return. */
! return build2 (code, compare_type,
! build2 (BIT_AND_EXPR, unsigned_type,
! make_bit_field_ref (linner, unsigned_type,
! nbitsize, nbitpos, 1),
! mask),
! build2 (BIT_AND_EXPR, unsigned_type,
! make_bit_field_ref (rinner, unsigned_type,
! nbitsize, nbitpos, 1),
! mask));
/* Otherwise, we are handling the constant case. See if the constant is too
big for the field. Warn and return a tree of for 0 (false) if so. We do
--- 3427,3445 ----
if (! const_p)
/* If not comparing with constant, just rework the comparison
and return. */
! return fold_build2 (code, compare_type,
! fold_build2 (BIT_AND_EXPR, unsigned_type,
! make_bit_field_ref (linner,
! unsigned_type,
! nbitsize, nbitpos,
! 1),
! mask),
! fold_build2 (BIT_AND_EXPR, unsigned_type,
! make_bit_field_ref (rinner,
! unsigned_type,
! nbitsize, nbitpos,
! 1),
! mask));
/* Otherwise, we are handling the constant case. See if the constant is too
big for the field. Warn and return a tree of for 0 (false) if so. We do
Roger
--