This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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);
}




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]