This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix missed VRP for unsigned addition
- From: Richard Guenther <rguenther at suse dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 24 Apr 2009 21:08:41 +0200 (CEST)
- Subject: [PATCH] Fix missed VRP for unsigned addition
This is a simple but common case where unsigned subtract causes
spurious overflow during range computations. Fixed by properly
handling the case when both additions overflow.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard.
2009-04-24 Richard Guenther <rguenther@suse.de>
* tree-vrp.c (extract_range_from_binary_expr): Handle overflow
from unsigned additions.
* gcc.dg/tree-ssa/vrp48.c: New testcase.
Index: gcc/tree-vrp.c
===================================================================
*** gcc/tree-vrp.c (revision 146590)
--- gcc/tree-vrp.c (working copy)
*************** extract_range_from_binary_expr (value_ra
*** 2248,2253 ****
--- 2248,2269 ----
the same end of each range. */
min = vrp_int_const_binop (code, vr0.min, vr1.min);
max = vrp_int_const_binop (code, vr0.max, vr1.max);
+
+ /* If both additions overflowed the range kind is still correct.
+ This happens regularly with subtracting something in unsigned
+ arithmetic.
+ ??? See PR30318 for all the cases we do not handle. */
+ if (code == PLUS_EXPR
+ && (TREE_OVERFLOW (min) && !is_overflow_infinity (min))
+ && (TREE_OVERFLOW (max) && !is_overflow_infinity (max)))
+ {
+ min = build_int_cst_wide (TREE_TYPE (min),
+ TREE_INT_CST_LOW (min),
+ TREE_INT_CST_HIGH (min));
+ max = build_int_cst_wide (TREE_TYPE (max),
+ TREE_INT_CST_LOW (max),
+ TREE_INT_CST_HIGH (max));
+ }
}
else if (code == MULT_EXPR
|| code == TRUNC_DIV_EXPR
Index: gcc/testsuite/gcc.dg/tree-ssa/vrp48.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/vrp48.c (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/vrp48.c (revision 0)
***************
*** 0 ****
--- 1,20 ----
+ extern void link_failure (void);
+
+ static int __attribute__ ((noinline)) foo (int x)
+ {
+ if (x >= 1)
+ if (x <= 10)
+ {
+ if (x < 1 || x > 10)
+ link_failure ();
+ x = x + 1;
+ }
+ return x;
+ }
+
+ int main (void)
+ {
+ int i = foo (0);
+ return 0;
+ }
+