gcc-patches@gcc.gnu.org
[Top] [All Lists]

[Patch] Fix PR23128 and PR23129

Subject: [Patch] Fix PR23128 and PR23129
From: James A. Morrison
Date: Sat, 30 Jul 2005 22:31:07 -0400
 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@xxxxxxxxxxx>

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



<Prev in Thread] Current Thread [Next in Thread>