This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[Patch] Fix PR23128 and PR23129
- From: ja2morri at csclub dot uwaterloo dot ca (James A. Morrison)
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 30 Jul 2005 22:31:07 -0400
- Subject: [Patch] Fix PR23128 and PR23129
Hi,
This patch fixes a few problem in VRP wrt unsigned types, it also sets
the value range of a division to VARYING if we only have anti-ranges and fixes
a missed optimization that I found while making up a testcase for unsigned
subtraction. This has been bootstrapped and regtested on ia64-linux with
no new failures. Ok for mainline?
The first two testcases go in gcc.dg/tree-ssa, the other 3 go in
gcc.c-torture/execute
:ADDPATCH SSA :
--
Thanks,
Jim
http://www.csclub.uwaterloo.ca/~ja2morri/
http://phython.blogspot.com
http://open.nit.ca/wiki/?page=jim
2005-07-30 James A. Morrison <phython@gcc.gnu.org>
PR tree-optimization/23128
PR tree-optimization/23129
* tree-vrp.c (vrp_int_const_binop): Treat unsigned types like
flag_wrapv.
(extract_range_from_binary_expr): Set value range to varying for
divisions with anti-ranges. Set value range to varying for unsigned
addition and subtraction if it could wrap.
(compare_ranges): Return false for EQ_EXPR if VR0 is less than VR1 or
vice-versa.
Index: tree-vrp.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/tree-vrp.c,v
retrieving revision 2.47
diff -u -p -r2.47 tree-vrp.c
--- tree-vrp.c 29 Jul 2005 15:21:54 -0000 2.47
+++ tree-vrp.c 30 Jul 2005 18:10:26 -0000
@@ -908,7 +908,7 @@ vrp_int_const_binop (enum tree_code code
{
tree res;
- if (flag_wrapv)
+ if (flag_wrapv || TYPE_UNSIGNED (TREE_TYPE (val1)))
return int_const_binop (code, val1, val2, 0);
/* If we are not using wrapping arithmetic, operate symbolically
@@ -1095,6 +1095,22 @@ extract_range_from_binary_expr (value_ra
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);
+
+ /* Check for possible unsigned wrapping. */
+ if (code == PLUS_EXPR && TYPE_UNSIGNED (TREE_TYPE (expr)))
+ {
+ tree res0 = fold_binary_to_constant (GT_EXPR, TREE_TYPE (expr),
+ vr0.max, max);
+ tree res1 = fold_binary_to_constant (GT_EXPR, TREE_TYPE (expr),
+ vr1.max, max);
+
+ if ((res0 && integer_onep (res0))
+ || (res1 && integer_onep (res1)))
+ {
+ set_value_range_to_varying (vr);
+ return;
+ }
+ }
}
else if (code == MULT_EXPR
|| code == TRUNC_DIV_EXPR
@@ -1136,7 +1152,8 @@ extract_range_from_binary_expr (value_ra
the new range. */
/* Divisions by zero result in a VARYING value. */
- if (code != MULT_EXPR && range_includes_zero_p (&vr1))
+ if (code != MULT_EXPR
+ && (vr0.type == VR_ANTI_RANGE || range_includes_zero_p (&vr1)))
{
set_value_range_to_varying (vr);
return;
@@ -1204,6 +1221,22 @@ extract_range_from_binary_expr (value_ra
each range. */
min = vrp_int_const_binop (code, vr0.min, vr1.max);
max = vrp_int_const_binop (code, vr0.max, vr1.min);
+
+ /* Check for possible unsigned wrapping. */
+ if (TYPE_UNSIGNED (TREE_TYPE (expr)))
+ {
+ tree res0 = fold_binary_to_constant (LT_EXPR, TREE_TYPE (expr),
+ vr0.min, min);
+ tree res1 = fold_binary_to_constant (GT_EXPR, TREE_TYPE (expr),
+ vr1.max, max);
+
+ if ((res0 && integer_onep (res0))
+ || (res1 && integer_onep (res1)))
+ {
+ set_value_range_to_varying (vr);
+ return;
+ }
+ }
}
else
gcc_unreachable ();
@@ -1677,6 +1710,10 @@ compare_ranges (enum tree_code comp, val
else if (cmp_min != -2 && cmp_max != -2)
return boolean_false_node;
}
+ /* If [V0_MIN, V1_MAX] < [V1_MIN, V1_MAX] then V0 != V1. */
+ else if (compare_values (vr0->min, vr1->max) == 1
+ || compare_values (vr1->min, vr0->max) == 1)
+ return boolean_false_node;
return NULL_TREE;
}
/* { dg-do compile } */
/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp" } */
extern void link_error ();
void test01(unsigned int a, unsigned int b)
{
unsigned int x = 0x80000000;
if (a < x)
if (b < x)
if (a > 5)
if (a + b == 0U)
link_error ();
}
void test02(unsigned int a, unsigned int b)
{
unsigned int x = 0x80000000;
if (a > x)
if (b < x)
if (a - b == 1U)
link_error ();
}
/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp" } } */
/* { dg-final { cleanup-tree-dump "vrp" } } */
/* { dg-do compile } */
/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp" } */
extern void link_error ();
void test02(unsigned int a, unsigned int b)
{
unsigned int x = 0x80000000;
if (a > x)
if (b < x)
if (a == b)
link_error ();
}
/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp" } } */
/* { dg-final { cleanup-tree-dump "vrp" } } */
extern void exit (int);
extern void abort ();
void test(unsigned int a, unsigned int b)
{
if (a < 5)
abort();
if (b < 5)
abort();
if (a + b != 0U)
abort();
}
int main(int argc, char *argv[])
{
unsigned int x = 0x80000000;
test(x, x);
exit (0);
}
extern void exit (int);
extern void abort ();
void test(int x, int y)
{
int c;
if (x == 1) abort();
if (y == 1) abort();
c = x / y;
if (c != 1) abort();
}
int main()
{
test(2, 2);
exit (0);
}
#include <limits.h>
extern void exit (int);
extern void abort ();
void test01(unsigned int a, unsigned int b)
{
if (a < 5)
abort();
if (b < 5)
abort();
if (a - b != 5)
abort();
}
void test02(unsigned int a, unsigned int b)
{
if (a >= 12)
if (b > 15)
if (a - b < UINT_MAX - 15U)
abort ();
}
int main(int argc, char *argv[])
{
unsigned x = 0x80000000;
test01(x + 5, x);
test02(14, 16);
exit (0);
}