[Bug tree-optimization/31130] [4.3 Regression] VRP no longer derives range for division after negation

2007-03-13 Thread rguenth at gcc dot gnu dot org


--- Comment #6 from rguenth at gcc dot gnu dot org  2007-03-13 09:30 ---
How tracking _two_ value ranges for signed quantities with undefined overflow.
One assuming it is undefined and one with wrapping semantics.  Whenever you
fold
something using the value range you warn if the folding result would differ
if using either or the other variant, if they do not differ, don't warn.  This
way you don't affect existing optimizations and strictly warn in the case the
transformation is done taking advantage of the undefined overflow.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31130



[Bug tree-optimization/31130] [4.3 Regression] VRP no longer derives range for division after negation

2007-03-12 Thread ian at airs dot com


--- Comment #4 from ian at airs dot com  2007-03-12 17:08 ---
First test case:

int f(int a)
{
  if (a  0)
a = -a;
  return a  0;
}

As far as I can tell the behaviour of this test case in VRP is unchanged by the
patch in this PR.  And the code is still fully optimized.

Second test case:

int f(int a)
{
  if (a  0)
a = -a;
  if (a  0)
a = -a;
  return a  0;
}

In my tests the second conditional is removed during the VRP pass with or
without the patch in this PR.  It is cleaned up by jump threading.

Third test case:

extern void link_error ();
void foo (int a)
{
  if (a  0)
{
  int y;
  a *=-2;
  y  = a / 7;
  if (y  1  30)
link_error ();
}
}

int main()
{
  return 0;
}

I agree that VRP does not sort this out, although the final generated code is
fine.  I personally think the overflow infinity code does the right thing here.

Fourth test case:

extern void link_error ();
void foo (int a)
{
  if (a  0)
{
  int y;
  y  = -a / 7;
  if (y  1  30)
link_error ();
}
}

This does give a warning with -Wstrict-overflow=4


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31130



[Bug tree-optimization/31130] [4.3 Regression] VRP no longer derives range for division after negation

2007-03-12 Thread ian at airs dot com


--- Comment #5 from ian at airs dot com  2007-03-12 17:21 ---
Unfortunately my patch in comment #1 doesn't handle this test case correctly:

extern void abort (void);
void
foo (int a)
{
  if (a = (int) 0x8001)
{
  a = - a;
  if (a  0)
abort ();
}
}

It turns it into if (a  0x8001) abort(); with no warning.  The
transformation is OK with -fstrict-overflow, but we should get a warning with
-Wstrict-overflow, because it assumes that -INT_MIN  0 is true.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31130



[Bug tree-optimization/31130] [4.3 Regression] VRP no longer derives range for division after negation

2007-03-11 Thread ian at airs dot com


--- Comment #1 from ian at airs dot com  2007-03-11 20:39 ---
I am testing this patch.

Index: gcc/tree-vrp.c
===
--- gcc/tree-vrp.c  (revision 122820)
+++ gcc/tree-vrp.c  (working copy)
@@ -2142,13 +2142,11 @@ extract_range_from_unary_expr (value_ran
min = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
   else if (needs_overflow_infinity (TREE_TYPE (expr)))
{
- if (supports_overflow_infinity (TREE_TYPE (expr)))
-   min = positive_overflow_infinity (TREE_TYPE (expr));
- else
-   {
- set_value_range_to_varying (vr);
- return;
-   }
+ /* Negating TYPE_MIN_VALUE gives us a minimum value of
+positive overflow infinity, and there is nothing useful
+we can do with such a range.  */
+ set_value_range_to_varying (vr);
+ return;
}
   else
min = TYPE_MIN_VALUE (TREE_TYPE (expr));
@@ -2161,8 +2159,16 @@ extract_range_from_unary_expr (value_ran
max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
   else if (needs_overflow_infinity (TREE_TYPE (expr)))
{
- if (supports_overflow_infinity (TREE_TYPE (expr)))
-   max = positive_overflow_infinity (TREE_TYPE (expr));
+ /* We have a non-overflowed TYPE_MIN as the minimum value.
+If TYPE_MIN is also the maximum value, then negating this
+gives us a positive overflow, and we just go straight to
+varying since we will get there anyhow at the bottom of
+this function.  Otherwise TYPE_MIN is a half-range
+[TYPE_MIN, X] without overflow, so we flip it to a
+half-range [-X, TYPE_MAX] without overflow.  */
+ if (vr0.max != TYPE_MIN_VALUE (TREE_TYPE (expr))
+  !is_negative_overflow_infinity (vr0.max))
+   max = TYPE_MAX_VALUE (TREE_TYPE (expr));
  else
{
  set_value_range_to_varying (vr);


-- 

ian at airs dot com changed:

   What|Removed |Added

 AssignedTo|unassigned at gcc dot gnu   |ian at airs dot com
   |dot org |
 Status|UNCONFIRMED |ASSIGNED
 Ever Confirmed|0   |1
   Last reconfirmed|-00-00 00:00:00 |2007-03-11 20:39:57
   date||


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31130



[Bug tree-optimization/31130] [4.3 Regression] VRP no longer derives range for division after negation

2007-03-11 Thread pinskia at gcc dot gnu dot org


--- Comment #2 from pinskia at gcc dot gnu dot org  2007-03-12 05:43 ---

- if (supports_overflow_infinity (TREE_TYPE (expr)))
-   min = positive_overflow_infinity (TREE_TYPE (expr));
- else
-   {
- set_value_range_to_varying (vr);
- return;
-   }
+ /* Negating TYPE_MIN_VALUE gives us a minimum value of
+positive overflow infinity, and there is nothing useful
+we can do with such a range.  */
+ set_value_range_to_varying (vr);


This seems to introduce another missed optimization regression:

int f(int a)
{
  if (a  0)
a = -a;
  return a  0;
}

A more complex example is where you do abs twice:
int f(int a)
{
  if (a  0)
a = -a;
  if (a  0)
a = -a;
  return a  0;
}

The second abs should be removed in VRP but now it will not be removed.

-- Pinski who is upset at all these changes to VRP.  Also who is upset we
change GCC for people who don't know the language they are writting in.


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31130



[Bug tree-optimization/31130] [4.3 Regression] VRP no longer derives range for division after negation

2007-03-11 Thread pinskia at gcc dot gnu dot org


--- Comment #3 from pinskia at gcc dot gnu dot org  2007-03-12 06:11 ---
How about:
extern void link_error ();
void foo (int a)
{
  if (a  0)
{
  int y;
  a *=-2;
  y  = a / 7;
  if (y  1  30)
link_error ();
}
}

int main()
{
  return 0;
}

Also?  Which is like the below testcase but is not just a = -a;

In fact it is weird to have:
extern void link_error ();
void foo (int a)
{
  if (a  0)
{
  int y;
  y  = -a / 7;
  if (y  1  30)
link_error ();
}
}

Work and not the testcase in comment #0 to work :)  In fact -Wstrict-overflow
does not even warn about the above testcase :), even though the transformation
between -a / 7 to a/-7 dependings on integer overflow being undefined.  Looks
like someone missed a case in fold-const.c :).  (note I added it so I
remembered about it). 


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=31130