diff mbox

i * i is nonnegative

Message ID alpine.DEB.2.02.1303191659110.4515@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse March 19, 2013, 4:08 p.m. UTC
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.

Comments

Jeff Law March 19, 2013, 4:21 p.m. UTC | #1
On 03/19/2013 10:08 AM, Marc Glisse wrote:
> 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.
Fine for the trunk.  Though I would suggest waiting for http service & 
web archives to return before committing.

BTW, did you check if VRP creates a non-negative range for this case as 
well?

jeff
Marc Glisse March 19, 2013, 4:41 p.m. UTC | #2
On Tue, 19 Mar 2013, Jeff Law wrote:

> On 03/19/2013 10:08 AM, Marc Glisse wrote:
>> 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.
> Fine for the trunk.  Though I would suggest waiting for http service & web 
> archives to return before committing.

Yep.

> BTW, did you check if VRP creates a non-negative range for this case as well?

It doesn't :-(

It would probably need to be done in extract_range_from_binary_expr since 
extract_range_from_binary_expr_1 does not see the expression, maybe after 
calling extract_range_from_binary_expr_1, and we would remove the negative 
part of the interval it returned.
diff mbox

Patch

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))