Patchwork i * i is nonnegative

login
register
mail settings
Submitter Marc Glisse
Date March 19, 2013, 4:08 p.m.
Message ID <alpine.DEB.2.02.1303191659110.4515@stedding.saclay.inria.fr>
Download mbox | patch
Permalink /patch/229107/
State New
Headers show

Comments

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

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