optimization/6909: problem w/ -Os on modified loop-2c.c test case.

Glen Nakamura glen@imodulo.com
Sun Jun 2 18:51:00 GMT 2002


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.

Notes: This patch is a variation of a similar one posted in regard to PR6822.
I added "code = ??_EXPR;" in a number of places to keep "code" and
"TREE_CODE (t)" in sync.  I couldn't think of a specific test case to expose
the problem, but I think it's correct and other places that use TREE_SET_CODE
do the same thing.

- Glen Nakamura

-------------- next part --------------
Index: fold-const.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.207
diff -c -3 -p -u -r1.207 fold-const.c
--- fold-const.c	1 Jun 2002 16:56:07 -0000	1.207
+++ fold-const.c	2 Jun 2002 21:32:28 -0000
@@ -5994,6 +5994,70 @@ fold (expr)
 	  }
       }
 
+      /* Change X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
+	 if CST is positive.  This transformation affects the cases which are
+	 handled in later optimizations involving comparisons with non-negative
+	 constants.  Remember to handle the equivalent > and <= cases instead
+	 of the >= and < cases.  Refer to the optimizations involving unsigned
+	 comparisons with 0 and comparisons with the highest possible integer
+	 of a specified type below for details of how this transformation
+	 affects them.  */
+      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.
+	 This optimization also applies to X >= 1 and X < 1 since those cases
+	 are converted to X > 0 and X <= 0 by a previous transformation
+	 which changes X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
+	 if CST is positive.  */
+      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;
+	    }
+	}
+
       /* Comparisons with the highest or lowest possible integer of
 	 the specified size will have known values and an unsigned
 	 <= 0x7fffffff can be simplified.  */
@@ -6017,6 +6081,7 @@ fold (expr)
 					   convert (type, integer_zero_node),
 					   arg0);
 		case GE_EXPR:
+		  code = EQ_EXPR;
 		  TREE_SET_CODE (t, EQ_EXPR);
 		  break;
 
@@ -6025,9 +6090,38 @@ fold (expr)
 					   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 a previous transformation changes
+		   X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
+		   if CST is positive.  The two new cases are handled
+		   in the next switch statement.  */
+
+		default:
+		  break;
+		}
+
+	    else if (TREE_INT_CST_HIGH (arg1) == 0
+		&& (TREE_INT_CST_LOW (arg1)
+		    == ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 2)
+		&& ! TREE_UNSIGNED (TREE_TYPE (arg1)))
+	      switch (TREE_CODE (t))
+		{
+		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;
 		}
@@ -6043,6 +6137,7 @@ fold (expr)
 					   convert (type, integer_zero_node),
 					   arg0);
 		case LE_EXPR:
+		  code = EQ_EXPR;
 		  TREE_SET_CODE (t, EQ_EXPR);
 		  break;
 
@@ -6051,6 +6146,7 @@ fold (expr)
 					   convert (type, integer_one_node),
 					   arg0);
 		case GT_EXPR:
+		  code = NE_EXPR;
 		  TREE_SET_CODE (t, NE_EXPR);
 		  break;
 
@@ -6065,6 +6161,10 @@ fold (expr)
 		     /* signed_type does not work on pointer types.  */
 		     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
 	      {
+		/* The following case also applies to X < (1 << (width - 1))
+		   and X >= (1 << (width - 1)) because a previous
+		   transformation changes X < CST to X <= (CST - 1)
+		   and X >= CST to X > (CST - 1) if CST is positive.  */
 		if (TREE_CODE (t) == LE_EXPR || TREE_CODE (t) == GT_EXPR)
 		  {
 		    tree st0, st1;
@@ -6076,6 +6176,7 @@ fold (expr)
 			      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)
@@ -6087,6 +6188,7 @@ fold (expr)
 					   convert (type, integer_zero_node),
 					   arg0);
 		case GE_EXPR:
+		  code = EQ_EXPR;
 		  TREE_SET_CODE (t, EQ_EXPR);
 		  break;
 
@@ -6095,67 +6197,43 @@ fold (expr)
 					   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 a previous transformation changes
+		   X >= CST to X > (CST - 1) and X < CST to X <= (CST - 1)
+		   if CST is positive.  The two new cases are handled
+		   in the next switch statement.  */
+
 		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;
-	    }
-	}
+	    else if (TREE_INT_CST_HIGH (arg1) == 0
+		     && (TREE_INT_CST_LOW (arg1)
+			 == ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 2)
+		     && TREE_UNSIGNED (TREE_TYPE (arg1)))
+	      switch (TREE_CODE (t))
+		{
+		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;
 
-      /* 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;
-	    }
-	}
+		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-bugs mailing list