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][no-undefined-overflow] Easy cases for TYPE_OVERFLOW_WRAPS removal


This removes checks for TYPE_OVERFLOW_WRAPS (which is always true now)
in easy cases in fold-const.c.

There is some suspicious code in negate_expr_p and fold_negate_expr:

     case EXACT_DIV_EXPR:
       /* In general we can't negate A / B, because if A is INT_MIN and
         B is 1, we may turn this into INT_MIN / -1 which is undefined
-        and actually traps on some architectures.  But if overflow is
-        undefined, we can negate, because - (INT_MIN / 1) is an
-        overflow.  */
-      if (INTEGRAL_TYPE_P (TREE_TYPE (t))
-         && !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t)))
+        and actually traps on some architectures.  */
+      if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
         break;
       return negate_expr_p (TREE_OPERAND (t, 1))
              || negate_expr_p (TREE_OPERAND (t, 0));

where the comment doesn't make sense to me.  Especially if overflow
is undefined we should not produce A / -1 as that may now contain
new undefined overflow that wasn't there.  Note that calling
negate_expr_p does _not_ mean that -(A/B) was actually computed!
Nor does any undefinedness deal with the other problem mentioned
in the comment, the trapping of INT_MIN / -1 on some architectures.

So I simply disabled this transformation for integer types completely.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to the
branch.

Richard.

2009-03-06  Richard Guenther  <rguenther@suse.de>

	* fold-const.c (negate_expr_p): Only do not negate integer
	constants if overflows on the type trap and the negation
	might overflow.  Remove superfluous TYPE_OVERFLOW_WRAPS checks.
	Do not negate divisions on integral types.
	(fold_negate_expr): Do not negate divisions on integral types.
	(build_range_check): Remove superfluous TYPE_OVERFLOW_WRAPS checks.
	(extract_muldiv_1): Likewise.
	(fold_unary): Likewise for (T1)(X * Y) to (T1)X * (T1)Y folding.
	Adjust folding to also apply to MULTNV_EXPR if NV is dropped
	on the result.

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 144665)
+++ gcc/fold-const.c	(working copy)
@@ -1121,14 +1121,12 @@ negate_expr_p (tree t)
   switch (TREE_CODE (t))
     {
     case INTEGER_CST:
-      if (TYPE_OVERFLOW_WRAPS (type))
-	return true;
+      if (TYPE_OVERFLOW_TRAPS (type))
+	return may_negate_without_overflow_p (t);
+      return true;
 
-      /* Check that -CST will not overflow type.  */
-      return may_negate_without_overflow_p (t);
     case BIT_NOT_EXPR:
-      return (INTEGRAL_TYPE_P (type)
-	      && TYPE_OVERFLOW_WRAPS (type));
+      return INTEGRAL_TYPE_P (type);
 
     case FIXED_CST:
     case REAL_CST:
@@ -1184,11 +1182,8 @@ negate_expr_p (tree t)
     case EXACT_DIV_EXPR:
       /* In general we can't negate A / B, because if A is INT_MIN and
 	 B is 1, we may turn this into INT_MIN / -1 which is undefined
-	 and actually traps on some architectures.  But if overflow is
-	 undefined, we can negate, because - (INT_MIN / 1) is an
-	 overflow.  */
-      if (INTEGRAL_TYPE_P (TREE_TYPE (t))
-	  && !TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (t)))
+	 and actually traps on some architectures.  */
+      if (INTEGRAL_TYPE_P (TREE_TYPE (t)))
         break;
       return negate_expr_p (TREE_OPERAND (t, 1))
              || negate_expr_p (TREE_OPERAND (t, 0));
@@ -1355,33 +1350,17 @@ fold_negate_expr (tree t)
     case EXACT_DIV_EXPR:
       /* In general we can't negate A / B, because if A is INT_MIN and
 	 B is 1, we may turn this into INT_MIN / -1 which is undefined
-	 and actually traps on some architectures.  But if overflow is
-	 undefined, we can negate, because - (INT_MIN / 1) is an
-	 overflow.  */
-      if (!INTEGRAL_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
+	 and actually traps on some architectures.  */
+      if (!INTEGRAL_TYPE_P (type))
         {
-	  const char * const warnmsg = G_("assuming signed overflow does not "
-					  "occur when negating a division");
           tem = TREE_OPERAND (t, 1);
           if (negate_expr_p (tem))
-	    {
-	      if (INTEGRAL_TYPE_P (type)
-		  && (TREE_CODE (tem) != INTEGER_CST
-		      || integer_onep (tem)))
-		fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MISC);
-	      return fold_build2 (TREE_CODE (t), type,
-				  TREE_OPERAND (t, 0), negate_expr (tem));
-	    }
+	    return fold_build2 (TREE_CODE (t), type,
+				TREE_OPERAND (t, 0), negate_expr (tem));
           tem = TREE_OPERAND (t, 0);
           if (negate_expr_p (tem))
-	    {
-	      if (INTEGRAL_TYPE_P (type)
-		  && (TREE_CODE (tem) != INTEGER_CST
-		      || tree_int_cst_equal (tem, TYPE_MIN_VALUE (type))))
-		fold_overflow_warning (warnmsg, WARN_STRICT_OVERFLOW_MISC);
-	      return fold_build2 (TREE_CODE (t), type,
-				  negate_expr (tem), TREE_OPERAND (t, 1));
-	    }
+	    return fold_build2 (TREE_CODE (t), type,
+				negate_expr (tem), TREE_OPERAND (t, 1));
         }
       break;
 
@@ -4759,27 +4738,6 @@ build_range_check (tree type, tree exp,
       break;
     }
 
-  /* If we don't have wrap-around arithmetics upfront, try to force it.  */
-  if (TREE_CODE (etype) == INTEGER_TYPE
-      && !TYPE_OVERFLOW_WRAPS (etype))
-    {
-      tree utype, minv, maxv;
-
-      /* Check if (unsigned) INT_MAX + 1 == (unsigned) INT_MIN
-	 for the type in question, as we rely on this here.  */
-      utype = unsigned_type_for (etype);
-      maxv = fold_convert (utype, TYPE_MAX_VALUE (etype));
-      maxv = range_binop (PLUS_EXPR, NULL_TREE, maxv, 1,
-			  integer_one_node, 1);
-      minv = fold_convert (utype, TYPE_MIN_VALUE (etype));
-
-      if (integer_zerop (range_binop (NE_EXPR, integer_type_node,
-				      minv, 1, maxv, 1)))
-	etype = utype;
-      else
-	return 0;
-    }
-
   high = fold_convert (etype, high);
   low = fold_convert (etype, low);
   exp = fold_convert (etype, exp);
@@ -6235,15 +6193,13 @@ extract_muldiv_1 (tree t, tree c, enum t
 	}
 
       /* If it's a multiply or a division/modulus operation of a multiple
-         of our constant, do the operation and verify it doesn't overflow.  */
+         of our constant, do the operation.  */
       if (code == MULT_EXPR
 	  || integer_zerop (const_binop (TRUNC_MOD_EXPR, op1, c, 0)))
 	{
 	  op1 = const_binop (code, fold_convert (ctype, op1),
 			     fold_convert (ctype, c), 0);
-	  /* We allow the constant to overflow with wrapping semantics.  */
-	  if (op1 == 0
-	      || (TREE_OVERFLOW (op1) && !TYPE_OVERFLOW_WRAPS (ctype)))
+	  if (op1 == 0)
 	    break;
 	}
       else
@@ -8355,26 +8311,16 @@ fold_unary (enum tree_code code, tree ty
       /* Convert (T1)(X * Y) into (T1)X * (T1)Y if T1 is narrower than the
 	 type of X and Y (integer types only).  */
       if (INTEGRAL_TYPE_P (type)
-	  && TREE_CODE (op0) == MULT_EXPR
+	  && MULT_EXPR_P (op0)
 	  && INTEGRAL_TYPE_P (TREE_TYPE (op0))
 	  && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (op0)))
 	{
-	  /* Be careful not to introduce new overflows.  */
-	  tree mult_type;
-          if (TYPE_OVERFLOW_WRAPS (type))
-	    mult_type = type;
-	  else
-	    mult_type = unsigned_type_for (type);
-
-	  if (TYPE_PRECISION (mult_type) < TYPE_PRECISION (TREE_TYPE (op0)))
-	    {
-	      tem = fold_build2 (MULT_EXPR, mult_type,
-				 fold_convert (mult_type,
-					       TREE_OPERAND (op0, 0)),
-				 fold_convert (mult_type,
-					       TREE_OPERAND (op0, 1)));
-	      return fold_convert (type, tem);
-	    }
+	  /* Be careful to fall back to MULT_EXPR from MULTNV_EXPR.  */
+	  return fold_build2 (MULT_EXPR, type,
+			      fold_convert (type,
+					    TREE_OPERAND (op0, 0)),
+			      fold_convert (type,
+					    TREE_OPERAND (op0, 1)));
 	}
 
       tem = fold_convert_const (code, type, op0);


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