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]

i * i is nonnegative


Hello,

this patch extends the property that x*x is non-negative, which was already known for floats, to integers with undefined overflow.

2013-03-19  Marc Glisse  <marc.glisse@inria.fr>

	PR tree-optimization/56355
gcc/
	* fold-const.c (tree_binary_nonnegative_warnv_p) <MULT_EXPR>:
	Also handle integers with undefined overflow.

gcc/testsuite/
	* gcc.dg/pr56355-1.c: New file.

--
Marc Glisse
Index: gcc/testsuite/gcc.dg/pr56355-1.c
===================================================================
--- gcc/testsuite/gcc.dg/pr56355-1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pr56355-1.c	(revision 0)
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wstrict-overflow=4" } */
+
+int
+f (int i)
+{
+  return __builtin_abs (i * i); /* { dg-warning "assuming signed overflow" } */
+}

Property changes on: gcc/testsuite/gcc.dg/pr56355-1.c
___________________________________________________________________
Added: svn:eol-style
   + native
Added: svn:keywords
   + Author Date Id Revision URL

Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c	(revision 196633)
+++ gcc/fold-const.c	(working copy)
@@ -15286,29 +15286,32 @@ tree_binary_nonnegative_warnv_p (enum tr
 	      && TREE_CODE (inner2) == INTEGER_TYPE && TYPE_UNSIGNED (inner2))
 	    {
 	      unsigned int prec = MAX (TYPE_PRECISION (inner1),
 				       TYPE_PRECISION (inner2)) + 1;
 	      return prec < TYPE_PRECISION (type);
 	    }
 	}
       break;
 
     case MULT_EXPR:
-      if (FLOAT_TYPE_P (type))
+      if (FLOAT_TYPE_P (type) || TYPE_OVERFLOW_UNDEFINED (type))
 	{
-	  /* x * x for floating point x is always non-negative.  */
-	  if (operand_equal_p (op0, op1, 0))
-	    return true;
-	  return (tree_expr_nonnegative_warnv_p (op0,
-						 strict_overflow_p)
-		  && tree_expr_nonnegative_warnv_p (op1,
-						    strict_overflow_p));
+	  /* x * x is always non-negative for floating point x
+	     or without overflow.  */
+	  if (operand_equal_p (op0, op1, 0)
+	      || (tree_expr_nonnegative_warnv_p (op0, strict_overflow_p)
+		  && tree_expr_nonnegative_warnv_p (op1, strict_overflow_p)))
+	    {
+	      if (TYPE_OVERFLOW_UNDEFINED (type))
+		*strict_overflow_p = true;
+	      return true;
+	    }
 	}
 
       /* zero_extend(x) * zero_extend(y) is non-negative if x and y are
 	 both unsigned and their total bits is shorter than the result.  */
       if (TREE_CODE (type) == INTEGER_TYPE
 	  && (TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == INTEGER_CST)
 	  && (TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == INTEGER_CST))
 	{
 	  tree inner0 = (TREE_CODE (op0) == NOP_EXPR)
 	    ? TREE_TYPE (TREE_OPERAND (op0, 0))

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