This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] PR opt/3995: Optimize (A&C)!=0 into A<0



This patch implements the optimization suggested in PR opt/3995.
We can convert (A & C) != 0 into A < 0 and (A & C) == 0 into
A >= 0, when C is the integer constant representing the sign
bit of the signed integral type of A.  As analyzed by Richard
Henderson, this is sufficient to turn "c && !(c & 0x80)" into
"c > 0" for "char c".  Current CVS generates an obviously poor
sequence without this patch.

One subtlety of this patch is that we also need to be able to
handle the case (sign_extend(A) & C) != 0, which is handled
recursively in the new sign_bit_p predicate.

This patch also recursively calls "fold" after transforming code
like "(A & C) == C" into "(A & C) != 0".  This way if the constant
C is the sign bit of A, both transformations will get applied.


Finally, this patch also contains an obvious fix to a typo in the
comment describing the function fold_binary_op_with_conditional_arg.


Tested with a "make bootstrap" and "make -k check" on i686-pc-linux-gnu
with no new regressions.  Ok for mainline and to close PR opt/3995?

I'd really appreciate it if the reviewer could also cast an eye over
the patch at http://gcc.gnu.org/ml/gcc-patches/2002-04/msg00748.html
which fixes the compilation warnings in fold-const.c.  I feel a bit
uncomfortable proposing patches to source files that have warnings.


Many thanks in advance,



2002-05-04  Roger Sayle  <roger@eyesopen.com>
	PR opt/3995.
	* fold-const.c (sign_bit_p): New function.
	(fold) [EQ_EXPR]: Use this to convert (A & C) == 0 into A >= 0 and
        (A & C) != 0 into A < 0, when constant C is the sign bit of A's type.
	Reapply fold when converting (A & C) == C into (A & C) != 0.
	(fold_binary_op_with_conditional_arg): Fix typo in comment.


Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.198
diff -c -3 -p -r1.198 fold-const.c
*** fold-const.c	23 Apr 2002 23:31:02 -0000	1.198
--- fold-const.c	4 May 2002 21:46:31 -0000
*************** static tree decode_field_reference PARAM
*** 86,91 ****
--- 86,92 ----
  					    enum machine_mode *, int *,
  					    int *, tree *, tree *));
  static int all_ones_mask_p	PARAMS ((tree, int));
+ static int sign_bit_p		PARAMS ((tree, tree));
  static int simple_operand_p	PARAMS ((tree));
  static tree range_binop		PARAMS ((enum tree_code, tree, tree, int,
  					 tree, int));
*************** all_ones_mask_p (mask, size)
*** 2633,2638 ****
--- 2634,2686 ----
  				     size_int (precision - size), 0));
  }

+ /* Subroutine for fold: determine if VAL is the INTEGER_CONST that
+    represents the sign bit of EXP's type.  If EXP represents a sign
+    extension, also test VAL against the unextended type.  */
+
+ static int
+ sign_bit_p (exp, val)
+      tree exp;
+      tree val;
+ {
+   unsigned HOST_WIDE_INT lo;
+   HOST_WIDE_INT hi;
+   int width;
+   tree t;
+
+   /* Tree EXP must have a signed integral type.  */
+   t = TREE_TYPE (exp);
+   if (! INTEGRAL_TYPE_P (t) || TREE_UNSIGNED (t))
+     return 0;
+
+   /* Tree VAL must be an integer constant.  */
+   if (TREE_CODE (val) != INTEGER_CST
+       || TREE_CONSTANT_OVERFLOW (val))
+     return 0;
+
+   width = TYPE_PRECISION (t);
+   if (width > HOST_BITS_PER_WIDE_INT)
+     {
+       hi = (unsigned HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT);
+       lo = 0;
+     }
+   else
+     {
+       hi = 0;
+       lo = (unsigned HOST_WIDE_INT) 1 << (width - 1);
+     }
+
+   if (TREE_INT_CST_HIGH (val) == hi && TREE_INT_CST_LOW (val) == lo)
+     return 1;
+
+   /* Handle sign extension from a narrower type.  */
+   if (TREE_CODE (exp) == NOP_EXPR
+       && TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0))) < width)
+     return sign_bit_p (TREE_OPERAND (exp, 0), val);
+
+   return 0;
+ }
+
  /* Subroutine for fold_truthop: determine if an operand is simple enough
     to be evaluated unconditionally.  */

*************** count_cond (expr, lim)
*** 4172,4178 ****
    return MIN (lim, 1 + ctrue + cfalse);
  }

! /* Transform `a + (b ? x : y)' into `x ? (a + b) : (a + y)'.
     Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'.  Here
     CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
     expression, and ARG to `a'.  If COND_FIRST_P is non-zero, then the
--- 4220,4226 ----
    return MIN (lim, 1 + ctrue + cfalse);
  }

! /* Transform `a + (b ? x : y)' into `b ? (a + x) : (a + y)'.
     Transform, `a + (x < y)' into `(x < y) ? (a + 1) : (a + 0)'.  Here
     CODE corresponds to the `+', COND to the `(b ? x : y)' or `(x < y)'
     expression, and ARG to `a'.  If COND_FIRST_P is non-zero, then the
*************** fold (expr)
*** 6047,6054 ****
  	  && TREE_CODE (arg0) == BIT_AND_EXPR
  	  && integer_pow2p (TREE_OPERAND (arg0, 1))
  	  && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
! 	return build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
! 		      arg0, integer_zero_node);

        /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
  	 and similarly for >= into !=.  */
--- 6095,6111 ----
  	  && TREE_CODE (arg0) == BIT_AND_EXPR
  	  && integer_pow2p (TREE_OPERAND (arg0, 1))
  	  && operand_equal_p (TREE_OPERAND (arg0, 1), arg1, 0))
! 	return fold (build (code == EQ_EXPR ? NE_EXPR : EQ_EXPR, type,
! 			    arg0, integer_zero_node));
!
!       /* If we have (A & C) != 0 where C is the sign bit of A, convert
! 	 this into A < 0.  Similarly for (A & C) == 0 into A >= 0.  */
!       if ((code == EQ_EXPR || code == NE_EXPR)
! 	  && TREE_CODE (arg0) == BIT_AND_EXPR
! 	  && integer_zerop (arg1)
! 	  && sign_bit_p (TREE_OPERAND (arg0, 0), TREE_OPERAND (arg0, 1)))
! 	return fold (build (code == EQ_EXPR ? GE_EXPR : LT_EXPR, type,
! 			    TREE_OPERAND (arg0, 0), integer_zero_node));

        /* If X is unsigned, convert X < (1 << Y) into X >> Y == 0
  	 and similarly for >= into !=.  */

Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]