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] Eliminate signed sizetypes (1/3)


Every compiler in the GNU collection can choose to use either signed or 
unsigned sizetypes (exclusively, mixed signedness isn't allowed); the Ada 
compiler uses signed ones, all the other compilers (including LTO) use 
unsigned ones.  As a consequence, LTO doesn't really work with Ada, even 
intra-language LTO.

So I'm proposing to eliminate signed sizetypes from the middle-end altogether, 
so that people aren't tempted to make the wrong choice anymore :-), switching
the Ada compiler over to unsigned sizetypes in the process.  As a bonus, this 
will also fix bugs in some corner cases for Ada.

The delicate part is converting the Ada compiler because it is still relying 
heavily on subtle overflow handling for sizetypes and flipping the signedness 
changes the semantics.  This dependency should probably be reworked at some 
point, but this won't be easy at all and is not planned yet.

The attached first patch contains changes to the constant folder necessary to 
properly support overflow in unsigned sizetypes; nothing new, this support is 
already there, but it has been slightly damaged, especially by the fix for PR 
middle-end/32628, so the patch undoes it and fixes the problem differently.

The second patch will be the gigi patch and the third patch the one really 
eliminating signed sizetypes from the middle-end.

Tested on x86_64-suse-linux and i586-suse-linux, OK for mainline?


2010-04-13  Eric Botcazou  <ebotcazou@adacore.com>

	PR middle-end/32628
	* c-common.c (pointer_int_sum): Disregard overflow that occured only
	because of sign-extension change when converting to sizetype here...
	* fold-const.c (fold_convert_const_int_from_int): ...and not here.

	* fold-const.c (fold_binary_op_with_conditional_arg): Do not restrict
	the folding to constants.  Remove redundant final conversion.
	(fold_binary) <associate>: Do not associate if the re-association of
	constants alone overflows.
	(fold_binary) <FLOOR_MOD_EXPR>: Move transformation into BIT_AND_EXPR
	to the end of the list.
	(multiple_of_p) <COND_EXPR>: New case.


-- 
Eric Botcazou
Index: c-common.c
===================================================================
--- c-common.c	(revision 158246)
+++ c-common.c	(working copy)
@@ -3806,12 +3806,17 @@ pointer_int_sum (location_t loc, enum tr
 					     TYPE_UNSIGNED (sizetype)), intop);
 
   /* Replace the integer argument with a suitable product by the object size.
-     Do this multiplication as signed, then convert to the appropriate
-     type for the pointer operation.  */
-  intop = convert (sizetype,
-		   build_binary_op (loc,
-				    MULT_EXPR, intop,
-				    convert (TREE_TYPE (intop), size_exp), 1));
+     Do this multiplication as signed, then convert to the appropriate type
+     for the pointer operation and disregard an overflow that occured only
+     because of the sign-extension change in the latter conversion.  */
+  {
+    tree t = build_binary_op (loc,
+			      MULT_EXPR, intop,
+			      convert (TREE_TYPE (intop), size_exp), 1);
+    intop = convert (sizetype, t);
+    if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
+      TREE_OVERFLOW (intop) = 0;
+  }
 
   /* Create the sum or difference.  */
   if (resultcode == MINUS_EXPR)
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 158246)
+++ fold-const.c	(working copy)
@@ -2252,23 +2252,7 @@ fold_convert_const_int_from_int (tree ty
      appropriately sign-extended or truncated.  */
   t = force_fit_type_double (type, TREE_INT_CST_LOW (arg1),
 			     TREE_INT_CST_HIGH (arg1),
-		             /* Don't set the overflow when
-		      		converting from a pointer,  */
-			     !POINTER_TYPE_P (TREE_TYPE (arg1))
-			     /* or to a sizetype with same signedness
-				and the precision is unchanged.
-				???  sizetype is always sign-extended,
-				but its signedness depends on the
-				frontend.  Thus we see spurious overflows
-				here if we do not check this.  */
-			     && !((TYPE_PRECISION (TREE_TYPE (arg1))
-				   == TYPE_PRECISION (type))
-				  && (TYPE_UNSIGNED (TREE_TYPE (arg1))
-				      == TYPE_UNSIGNED (type))
-				  && ((TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
-				       && TYPE_IS_SIZETYPE (TREE_TYPE (arg1)))
-				      || (TREE_CODE (type) == INTEGER_TYPE
-					  && TYPE_IS_SIZETYPE (type)))),
+			     !POINTER_TYPE_P (TREE_TYPE (arg1)),
 			     (TREE_INT_CST_HIGH (arg1) < 0
 		 	      && (TYPE_UNSIGNED (type)
 				  < TYPE_UNSIGNED (TREE_TYPE (arg1))))
@@ -6731,12 +6715,6 @@ fold_binary_op_with_conditional_arg (loc
   tree lhs = NULL_TREE;
   tree rhs = NULL_TREE;
 
-  /* This transformation is only worthwhile if we don't have to wrap
-     arg in a SAVE_EXPR, and the operation can be simplified on at least
-     one of the branches once its pushed inside the COND_EXPR.  */
-  if (!TREE_CONSTANT (arg))
-    return NULL_TREE;
-
   if (TREE_CODE (cond) == COND_EXPR)
     {
       test = TREE_OPERAND (cond, 0);
@@ -6758,6 +6736,14 @@ fold_binary_op_with_conditional_arg (loc
       false_value = constant_boolean_node (false, testtype);
     }
 
+  /* This transformation is only worthwhile if we don't have to wrap ARG
+     in a SAVE_EXPR and the operation can be simplified on at least one
+     of the branches once its pushed inside the COND_EXPR.  */
+  if (!TREE_CONSTANT (arg)
+      && (TREE_SIDE_EFFECTS (arg)
+	  || TREE_CONSTANT (true_value) || TREE_CONSTANT (false_value)))
+    return NULL_TREE;
+
   arg = fold_convert_loc (loc, arg_type, arg);
   if (lhs == 0)
     {
@@ -6776,8 +6762,11 @@ fold_binary_op_with_conditional_arg (loc
 	rhs = fold_build2_loc (loc, code, type, arg, false_value);
     }
 
-  test = fold_build3_loc (loc, COND_EXPR, type, test, lhs, rhs);
-  return fold_convert_loc (loc, type, test);
+  /* Check that we have simplified at least one of the branches.  */
+  if (!TREE_CONSTANT (arg) && !TREE_CONSTANT (lhs) && !TREE_CONSTANT (rhs))
+    return NULL_TREE;
+
+  return fold_build3_loc (loc, COND_EXPR, type, test, lhs, rhs);
 }
 
 
@@ -10628,23 +10617,39 @@ fold_binary_loc (location_t loc,
 	  var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
 			     code == MINUS_EXPR);
 
-	  /* With undefined overflow we can only associate constants
-	     with one variable.  */
-	  if (((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
-	       || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
-	      && var0 && var1)
-	    {
-	      tree tmp0 = var0;
-	      tree tmp1 = var1;
-
-	      if (TREE_CODE (tmp0) == NEGATE_EXPR)
-	        tmp0 = TREE_OPERAND (tmp0, 0);
-	      if (TREE_CODE (tmp1) == NEGATE_EXPR)
-	        tmp1 = TREE_OPERAND (tmp1, 0);
-	      /* The only case we can still associate with two variables
-		 is if they are the same, modulo negation.  */
-	      if (!operand_equal_p (tmp0, tmp1, 0))
-	        ok = false;
+	  /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
+	  if (code == MINUS_EXPR)
+	    code = PLUS_EXPR;
+
+	  /* With undefined overflow we can only associate constants with one
+	     variable, and constants whose association doesn't overflow.  */
+	  if ((POINTER_TYPE_P (type) && POINTER_TYPE_OVERFLOW_UNDEFINED)
+	      || (INTEGRAL_TYPE_P (type) && !TYPE_OVERFLOW_WRAPS (type)))
+	    {
+	      if (var0 && var1)
+		{
+		  tree tmp0 = var0;
+		  tree tmp1 = var1;
+
+		  if (TREE_CODE (tmp0) == NEGATE_EXPR)
+		    tmp0 = TREE_OPERAND (tmp0, 0);
+		  if (TREE_CODE (tmp1) == NEGATE_EXPR)
+		    tmp1 = TREE_OPERAND (tmp1, 0);
+		  /* The only case we can still associate with two variables
+		     is if they are the same, modulo negation.  */
+		  if (!operand_equal_p (tmp0, tmp1, 0))
+		    ok = false;
+		}
+
+	      if (ok && lit0 && lit1)
+		{
+		  tree tmp0 = fold_convert (type, lit0);
+		  tree tmp1 = fold_convert (type, lit1);
+
+		  if (!TREE_OVERFLOW (tmp0) && !TREE_OVERFLOW (tmp1)
+		      && TREE_OVERFLOW (fold_build2 (code, type, tmp0, tmp1)))
+		    ok = false;
+		}
 	    }
 
 	  /* Only do something if we found more than two objects.  Otherwise,
@@ -10655,10 +10660,6 @@ fold_binary_loc (location_t loc,
 		       + (lit0 != 0) + (lit1 != 0)
 		       + (minus_lit0 != 0) + (minus_lit1 != 0))))
 	    {
-	      /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
-	      if (code == MINUS_EXPR)
-		code = PLUS_EXPR;
-
 	      var0 = associate_trees (loc, var0, var1, code, type);
 	      con0 = associate_trees (loc, con0, con1, code, type);
 	      lit0 = associate_trees (loc, lit0, lit1, code, type);
@@ -12222,34 +12223,6 @@ fold_binary_loc (location_t loc,
 	  && TREE_INT_CST_HIGH (arg1) == -1)
 	return omit_one_operand_loc (loc, type, integer_zero_node, arg0);
 
-      /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
-         i.e. "X % C" into "X & (C - 1)", if X and C are positive.  */
-      strict_overflow_p = false;
-      if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
-	  && (TYPE_UNSIGNED (type)
-	      || tree_expr_nonnegative_warnv_p (op0, &strict_overflow_p)))
-	{
-	  tree c = arg1;
-	  /* Also optimize A % (C << N)  where C is a power of 2,
-	     to A & ((C << N) - 1).  */
-	  if (TREE_CODE (arg1) == LSHIFT_EXPR)
-	    c = TREE_OPERAND (arg1, 0);
-
-	  if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
-	    {
-	      tree mask = fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (arg1), arg1,
-				       build_int_cst (TREE_TYPE (arg1), 1));
-	      if (strict_overflow_p)
-		fold_overflow_warning (("assuming signed overflow does not "
-					"occur when simplifying "
-					"X % (power of two)"),
-				       WARN_STRICT_OVERFLOW_MISC);
-	      return fold_build2_loc (loc, BIT_AND_EXPR, type,
-				  fold_convert_loc (loc, type, arg0),
-				  fold_convert_loc (loc, type, mask));
-	    }
-	}
-
       /* X % -C is the same as X % C.  */
       if (code == TRUNC_MOD_EXPR
 	  && !TYPE_UNSIGNED (type)
@@ -12273,6 +12246,7 @@ fold_binary_loc (location_t loc,
 			    fold_convert_loc (loc, type,
 					      TREE_OPERAND (arg1, 0)));
 
+      strict_overflow_p = false;
       if (TREE_CODE (arg1) == INTEGER_CST
 	  && 0 != (tem = extract_muldiv (op0, arg1, code, NULL_TREE,
 					 &strict_overflow_p)))
@@ -12284,6 +12258,34 @@ fold_binary_loc (location_t loc,
 	  return fold_convert_loc (loc, type, tem);
 	}
 
+      /* Optimize TRUNC_MOD_EXPR by a power of two into a BIT_AND_EXPR,
+         i.e. "X % C" into "X & (C - 1)", if X and C are positive.  */
+      if ((code == TRUNC_MOD_EXPR || code == FLOOR_MOD_EXPR)
+	  && (TYPE_UNSIGNED (type)
+	      || tree_expr_nonnegative_warnv_p (op0, &strict_overflow_p)))
+	{
+	  tree c = arg1;
+	  /* Also optimize A % (C << N)  where C is a power of 2,
+	     to A & ((C << N) - 1).  */
+	  if (TREE_CODE (arg1) == LSHIFT_EXPR)
+	    c = TREE_OPERAND (arg1, 0);
+
+	  if (integer_pow2p (c) && tree_int_cst_sgn (c) > 0)
+	    {
+	      tree mask
+		= fold_build2_loc (loc, MINUS_EXPR, TREE_TYPE (arg1), arg1,
+				   build_int_cst (TREE_TYPE (arg1), 1));
+	      if (strict_overflow_p)
+		fold_overflow_warning (("assuming signed overflow does not "
+					"occur when simplifying "
+					"X % (power of two)"),
+				       WARN_STRICT_OVERFLOW_MISC);
+	      return fold_build2_loc (loc, BIT_AND_EXPR, type,
+				      fold_convert_loc (loc, type, arg0),
+				      fold_convert_loc (loc, type, mask));
+	    }
+	}
+
       return NULL_TREE;
 
     case LROTATE_EXPR:
@@ -14820,6 +14822,10 @@ multiple_of_p (tree type, const_tree top
     case SAVE_EXPR:
       return multiple_of_p (type, TREE_OPERAND (top, 0), bottom);
 
+    case COND_EXPR:
+      return (multiple_of_p (type, TREE_OPERAND (top, 1), bottom)
+	      && multiple_of_p (type, TREE_OPERAND (top, 2), bottom));
+
     case INTEGER_CST:
       if (TREE_CODE (bottom) != INTEGER_CST
 	  || integer_zerop (bottom)

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