[Committed] Use fold in optimize_bit_field_compare

Roger Sayle roger@eyesopen.com
Mon Nov 13 23:50:00 GMT 2006


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
--



More information about the Gcc-patches mailing list