[PATCH] Missing fold simplifications. (Fix PR6909 on mainline)

Richard Henderson rth@redhat.com
Fri Jun 14 17:05:00 GMT 2002


On Sun, Jun 02, 2002 at 03:58:26PM -1000, Glen Nakamura wrote:
> http://gcc.gnu.org/cgi-bin/gnatsweb.pl?cmd=view%20audit-trail&database=gcc&pr=6909
> 
> 2002-06-02  Glen Nakamura  <glen@imodulo.com>
> 
> 	* fold-const.c (fold): Move transformation of X >= CST to X > (CST - 1)
> 	and X < CST to X <= (CST - 1) to expose the following simplifications:
> 	  1. unsigned int < 0x80000000 to signed int >= 0.
> 	  2. unsigned int >= 0x80000000 to signed int < 0.
> 	  3. unsigned int > 0xfffffffe to unsigned int == 0xffffffff.
> 	  4. unsigned int <= 0xfffffffe to unsigned int != 0xffffffff.


I'm applying the following, which is simpler, but catches
the same sets of simplifications.


r~


	* fold-const.c (fold) [compare ops]: Move X>=C / X<C transfomation
	earlier.  Re-factor comparisons vs extrema.

Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.210
diff -c -p -d -u -r1.210 fold-const.c
--- fold-const.c	11 Jun 2002 22:36:53 -0000	1.210
+++ fold-const.c	14 Jun 2002 21:58:26 -0000
@@ -6013,9 +6013,34 @@ fold (expr)
 	  }
       }
 
+      /* Change X >= C to X > (C - 1) and X < C to X <= (C - 1) if C > 0.
+	 This transformation affects the cases which are handled in later
+	 optimizations involving comparisons with non-negative constants.  */
+      if (TREE_CODE (arg1) == INTEGER_CST
+	  && TREE_CODE (arg0) != INTEGER_CST
+	  && tree_int_cst_sgn (arg1) > 0)
+	{
+	  switch (code)
+	    {
+	    case GE_EXPR:
+	      code = GT_EXPR;
+	      arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+	      t = build (code, type, TREE_OPERAND (t, 0), arg1);
+	      break;
+
+	    case LT_EXPR:
+	      code = LE_EXPR;
+	      arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+	      t = build (code, type, TREE_OPERAND (t, 0), arg1);
+	      break;
+
+	    default:
+	      break;
+	    }
+	}
+
       /* Comparisons with the highest or lowest possible integer of
-	 the specified size will have known values and an unsigned
-	 <= 0x7fffffff can be simplified.  */
+	 the specified size will have known values.  */
       {
 	int width = GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (arg1)));
 
@@ -6025,43 +6050,76 @@ fold (expr)
 	    && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
 		|| POINTER_TYPE_P (TREE_TYPE (arg1))))
 	  {
+	    unsigned HOST_WIDE_INT signed_max;
+	    unsigned HOST_WIDE_INT max, min;
+
+	    signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
+
+	    if (TREE_UNSIGNED (TREE_TYPE (arg1)))
+	      {
+	        max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+		min = 0;
+	      }
+	    else
+	      {
+	        max = signed_max;
+		min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+	      }
+
 	    if (TREE_INT_CST_HIGH (arg1) == 0
-		&& (TREE_INT_CST_LOW (arg1)
-		    == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
-		&& ! TREE_UNSIGNED (TREE_TYPE (arg1)))
-	      switch (TREE_CODE (t))
+		&& TREE_INT_CST_LOW (arg1) == max)
+	      switch (code)
 		{
 		case GT_EXPR:
 		  return omit_one_operand (type,
 					   convert (type, integer_zero_node),
 					   arg0);
 		case GE_EXPR:
+		  code = EQ_EXPR;
 		  TREE_SET_CODE (t, EQ_EXPR);
 		  break;
-
 		case LE_EXPR:
 		  return omit_one_operand (type,
 					   convert (type, integer_one_node),
 					   arg0);
 		case LT_EXPR:
+		  code = NE_EXPR;
 		  TREE_SET_CODE (t, NE_EXPR);
 		  break;
 
+		/* The GE_EXPR and LT_EXPR cases above are not normally
+		   reached because of  previous transformations.  */
+
 		default:
 		  break;
 		}
-
-	    else if (TREE_INT_CST_HIGH (arg1) == -1
-		     && (TREE_INT_CST_LOW (arg1)
-			 == ((unsigned HOST_WIDE_INT) -1 << (width - 1)))
-		     && ! TREE_UNSIGNED (TREE_TYPE (arg1)))
-	      switch (TREE_CODE (t))
+	    else if (TREE_INT_CST_HIGH (arg1) == 0
+		     && TREE_INT_CST_LOW (arg1) == max - 1)
+	      switch (code)
+		{
+		case GT_EXPR:
+		  code = EQ_EXPR;
+		  arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+		  t = build (code, type, TREE_OPERAND (t, 0), arg1);
+		  break;
+		case LE_EXPR:
+		  code = NE_EXPR;
+		  arg1 = const_binop (PLUS_EXPR, arg1, integer_one_node, 0);
+		  t = build (code, type, TREE_OPERAND (t, 0), arg1);
+		  break;
+		default:
+		  break;
+		}
+	    else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
+		     && TREE_INT_CST_LOW (arg1) == min)
+	      switch (code)
 		{
 		case LT_EXPR:
 		  return omit_one_operand (type,
 					   convert (type, integer_zero_node),
 					   arg0);
 		case LE_EXPR:
+		  code = EQ_EXPR;
 		  TREE_SET_CODE (t, EQ_EXPR);
 		  break;
 
@@ -6070,111 +6128,52 @@ fold (expr)
 					   convert (type, integer_one_node),
 					   arg0);
 		case GT_EXPR:
+		  code = NE_EXPR;
 		  TREE_SET_CODE (t, NE_EXPR);
 		  break;
 
 		default:
 		  break;
 		}
+	    else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
+		     && TREE_INT_CST_LOW (arg1) == min + 1)
+	      switch (code)
+		{
+		case GE_EXPR:
+		  code = NE_EXPR;
+		  arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+		  t = build (code, type, TREE_OPERAND (t, 0), arg1);
+		  break;
+		case LT_EXPR:
+		  code = EQ_EXPR;
+		  arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
+		  t = build (code, type, TREE_OPERAND (t, 0), arg1);
+		  break;
+		default:
+		  break;
+		}
 
 	    else if (TREE_INT_CST_HIGH (arg1) == 0
-		     && (TREE_INT_CST_LOW (arg1)
-			 == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1)
+		     && TREE_INT_CST_LOW (arg1) == signed_max
 		     && TREE_UNSIGNED (TREE_TYPE (arg1))
 		     /* signed_type does not work on pointer types.  */
 		     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
 	      {
-		if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
+		/* The following case also applies to X < signed_max+1
+		   and X >= signed_max+1 because previous transformations.  */
+		if (code == LE_EXPR || code == GT_EXPR)
 		  {
 		    tree st0, st1;
 		    st0 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg0));
 		    st1 = (*lang_hooks.types.signed_type) (TREE_TYPE (arg1));
 		    return fold
-		      (build (TREE_CODE (t) == LE_EXPR ? GE_EXPR: LT_EXPR,
+		      (build (code == LE_EXPR ? GE_EXPR: LT_EXPR,
 			      type, convert (st0, arg0),
 			      convert (st1, integer_zero_node)));
 		  }
 	      }
-	    else if (TREE_INT_CST_HIGH (arg1) == 0
-		     && (TREE_INT_CST_LOW (arg1)
-			 == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1)
-		     && TREE_UNSIGNED (TREE_TYPE (arg1)))
-	      switch (TREE_CODE (t))
-		{
-		case GT_EXPR:
-		  return omit_one_operand (type,
-					   convert (type, integer_zero_node),
-					   arg0);
-		case GE_EXPR:
-		  TREE_SET_CODE (t, EQ_EXPR);
-		  break;
-
-		case LE_EXPR:
-		  return omit_one_operand (type,
-					   convert (type, integer_one_node),
-					   arg0);
-		case LT_EXPR:
-		  TREE_SET_CODE (t, NE_EXPR);
-		  break;
-
-		default:
-		  break;
-		}
 	  }
       }
-
-      /* Change X >= C to X > C-1 and X < C to X <= C-1 if C is positive.  */
-      if (TREE_CODE (arg1) == INTEGER_CST
-	  && TREE_CODE (arg0) != INTEGER_CST
-	  && tree_int_cst_sgn (arg1) > 0)
-	{
-	  switch (TREE_CODE (t))
-	    {
-	    case GE_EXPR:
-	      code = GT_EXPR;
-	      arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-	      t = build (code, type, TREE_OPERAND (t, 0), arg1);
-	      break;
-
-	    case LT_EXPR:
-	      code = LE_EXPR;
-	      arg1 = const_binop (MINUS_EXPR, arg1, integer_one_node, 0);
-	      t = build (code, type, TREE_OPERAND (t, 0), arg1);
-	      break;
-
-	    default:
-	      break;
-	    }
-	}
-
-      /* An unsigned comparison against 0 can be simplified.  */
-      if (integer_zerop (arg1)
-	  && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
-	      || POINTER_TYPE_P (TREE_TYPE (arg1)))
-	  && TREE_UNSIGNED (TREE_TYPE (arg1)))
-	{
-	  switch (TREE_CODE (t))
-	    {
-	    case GT_EXPR:
-	      code = NE_EXPR;
-	      TREE_SET_CODE (t, NE_EXPR);
-	      break;
-	    case LE_EXPR:
-	      code = EQ_EXPR;
-	      TREE_SET_CODE (t, EQ_EXPR);
-	      break;
-	    case GE_EXPR:
-	      return omit_one_operand (type,
-				       convert (type, integer_one_node),
-				       arg0);
-	    case LT_EXPR:
-	      return omit_one_operand (type,
-				       convert (type, integer_zero_node),
-				       arg0);
-	    default:
-	      break;
-	    }
-	}
 
       /* If this is an EQ or NE comparison of a constant with a PLUS_EXPR or
 	 a MINUS_EXPR of a constant, we can convert it into a comparison with



More information about the Gcc-patches mailing list