[Bug tree-optimization/31130] [4.3 Regression] VRP no longer derives range for division after negation
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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