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 PR 22493


Hi,

  This patch fixes how extract_range_from_unary_expr deals with NEGATE_EXPRs
and ABS_EXPRs for VR_ANTI_RANGEs and flag_wrapv.

 First we can't simply copy a VR_ANTI_RANGE for NEGATE_EXPRs since we could
have an anti-range that is ~[2, 2], so we can only copy the anti-range when
it is ~[-c, c].  vrp-1.c shows this problem.

 Similarily we have to be careful with anti-ranges and ABS_EXPRs, vrp-2.s shows
how VRP used to mess up.

 Also for ABS_EXPRs we only want to switch the order of the min and max values
in the range if both values are negative.  vrp-3.c shows this.  We used to
generate turn the range [-15, 12] into [12, 15] instead of [0, 15].

 The testcase in pr22493-1.c deals with flag_wrapv for NEGATE_EXPRs.  I have
a testcase for ABS_EXPRs as well, but it currently fails in the RTL optimizers.

 All of the testcases go in gcc.c-torture/execute.  This patch has been
bootstrapped and regtested on ia64-linux with no new regressions.  However,
very few of the libstdc++ tests actually ran.  This version of the patch also
fixes all the Divide_1 failures for java on ia64.  Ok for mainline?

-- 
Thanks,
Jim

http://www.csclub.uwaterloo.ca/~ja2morri/
http://phython.blogspot.com
http://open.nit.ca/wiki/?page=jim

2005-07-24  James A. Morrison  <phython@gcc.gnu.org>

	* tree-vrp.c (extract_range_from_unary_expr): Deal with -fwrapv and
	VR_ANTI_RANGEs properly for NEGATE_EXPRs and ABS_EXPRs.

Index: tree-vrp.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/tree-vrp.c,v
retrieving revision 2.42
diff -u -p -r2.42 tree-vrp.c
--- tree-vrp.c	20 Jul 2005 20:26:00 -0000	2.42
+++ tree-vrp.c	23 Jul 2005 22:25:10 -0000
@@ -1237,6 +1237,7 @@ extract_range_from_unary_expr (value_ran
 {
   enum tree_code code = TREE_CODE (expr);
   tree min, max, op0;
+  enum value_range_type vr_type;
   int cmp;
   value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
 
@@ -1265,8 +1266,10 @@ extract_range_from_unary_expr (value_ran
   else
     set_value_range_to_varying (&vr0);
 
+  vr_type = vr0.type;
+
   /* If VR0 is UNDEFINED, so is the result.  */
-  if (vr0.type == VR_UNDEFINED)
+  if (vr_type == VR_UNDEFINED)
     {
       set_value_range_to_undefined (vr);
       return;
@@ -1276,7 +1279,7 @@ extract_range_from_unary_expr (value_ran
      operand is neither a pointer nor an integral type, set the
      resulting range to VARYING.  TODO, in some cases we may be able
      to derive anti-ranges (like non-zero values).  */
-  if (vr0.type == VR_VARYING
+  if (vr_type == VR_VARYING
       || (!INTEGRAL_TYPE_P (TREE_TYPE (op0))
 	  && !POINTER_TYPE_P (TREE_TYPE (op0)))
       || symbolic_range_p (&vr0))
@@ -1312,7 +1315,7 @@ extract_range_from_unary_expr (value_ran
 	 or equal to the new max, then we can safely use the newly
 	 computed range for EXPR.  This allows us to compute
 	 accurate ranges through many casts.  */
-      if (vr0.type == VR_RANGE)
+      if (vr_type == VR_RANGE)
 	{
 	  tree new_min, new_max;
 
@@ -1353,27 +1356,64 @@ extract_range_from_unary_expr (value_ran
   if (code == NEGATE_EXPR
       && !TYPE_UNSIGNED (TREE_TYPE (expr)))
     {
-      /* Negating an anti-range doesn't really do anything to it.  The
-	 new range will also not take on the same range of values
-	 excluded by the original anti-range.  */
+      /* Negating an anti-range doesn't really do anything to it if the max
+	 value is equal to the min value.  Then the new range will also not
+	 take on the same range of values excluded by the original
+	 anti-range.  */
       if (vr0.type == VR_ANTI_RANGE)
 	{
-	  copy_value_range (vr, &vr0);
+	  tree neg_min = fold_unary_to_constant (code, TREE_TYPE (expr),
+						 vr0.min);
+	  if (operand_equal_p (vr0.max, neg_min, 0))
+	    copy_value_range (vr, &vr0);
+	  else
+	    set_value_range_to_varying (vr);
 	  return;
 	}
 
-      /* NEGATE_EXPR flips the range around.  */
-      min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr)))
-	    ? TYPE_MIN_VALUE (TREE_TYPE (expr))
-	    : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
+      if (flag_wrapv && vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
+	{
+	  tree one = build_int_cst (TREE_TYPE (expr), 1);
 
-      max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
-	    ? TYPE_MAX_VALUE (TREE_TYPE (expr))
-	    : fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
+	  vr_type = VR_ANTI_RANGE;
+	  max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
+    	  max = int_const_binop (MINUS_EXPR, max, one, 0);
+	  min = int_const_binop (PLUS_EXPR, vr0.min, one, 0);
+	}
+      else
+	{
+	  /* NEGATE_EXPR flips the range around.  */
+	  min = (vr0.max == TYPE_MAX_VALUE (TREE_TYPE (expr)))
+		? TYPE_MIN_VALUE (TREE_TYPE (expr))
+		: fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
+
+	  max = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
+		? TYPE_MAX_VALUE (TREE_TYPE (expr))
+		: fold_unary_to_constant (code, TREE_TYPE (expr), vr0.min);
+	}
     }
   else if (code == ABS_EXPR
-           && !TYPE_UNSIGNED (TREE_TYPE (expr)))
+           && !(TYPE_UNSIGNED (TREE_TYPE (expr))))
     {
+      int comp;
+      /* Deal with VR_ANTI_RANGEs in the same way we do for NEGATE_EXPRs.  */
+      if (vr_type == VR_ANTI_RANGE)
+	{
+	  tree neg_min = fold_unary_to_constant (NEGATE_EXPR, TREE_TYPE (expr),
+						 vr0.min);
+	  if (operand_equal_p (vr0.max, neg_min, 0))
+	    copy_value_range (vr, &vr0);
+	  else
+	    set_value_range_to_varying (vr);
+	  return;
+	}
+
+      if (flag_wrapv && vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
+	{
+	  set_value_range_to_varying (vr);
+	  return;
+	}
+	
       /* ABS_EXPR may flip the range around, if the original range
 	 included negative values.  */
       min = (vr0.min == TYPE_MIN_VALUE (TREE_TYPE (expr)))
@@ -1382,12 +1422,22 @@ extract_range_from_unary_expr (value_ran
 
       max = fold_unary_to_constant (code, TREE_TYPE (expr), vr0.max);
 
-      /* If the range was reversed, swap MIN and MAX.  */
-      if (compare_values (min, max) == 1)
+      comp = compare_values (min, max);
+      if (tree_int_cst_sgn (vr0.min) == tree_int_cst_sgn (vr0.max))
+	{
+          /* If the range was reversed, swap MIN and MAX.  */
+	  if (comp == 1)
+	    {
+	      tree t = min;
+	      min = max;
+	      max = t;
+	    }
+	}
+      else
 	{
-	  tree t = min;
-	  min = max;
-	  max = t;
+	  if (comp == 1)
+	    max = min;
+	  min = build_int_cst (TREE_TYPE (expr), 0);
 	}
     }
   else
@@ -1406,7 +1456,7 @@ extract_range_from_unary_expr (value_ran
       set_value_range_to_varying (vr);
     }
   else
-    set_value_range (vr, vr0.type, min, max, NULL);
+    set_value_range (vr, vr_type, min, max, NULL);
 }
 
 
#include <limits.h>
extern void abort ();
extern void exit (int);
void f(int i)
{
  if (i>0)
    abort();
  i = -i;
  if (i<0)
    return;
  abort ();
}

int main(int argc, char *argv[])
{
  f(INT_MIN);
  exit (0);
}

Attachment: pr22493-1.x
Description: Binary data

extern void abort ();
extern void exit (int);

int f (int a) {
	if (a != 2) {
		a = -a;
		if (a == 2)
		  return 0;
		return 1;
	}
	return 1;
}

int main (int argc, char *argv[]) {
	if (f (-2))
		abort ();
	exit (0);
}

extern void abort ();
extern void exit (int);

int f (int a) {
	if (a != 2) {
		a = a > 0 ? a : -a;
		if (a == 2)
		  return 0;
		return 1;
	}
	return 1;
}

int main (int argc, char *argv[]) {
	if (f (-2))
		abort ();
	exit (0);
}

extern void abort ();
extern void exit (int);

int f (int a) {
	if (a < 12) {
	  if (a > -15) {
		a = a > 0 ? a : -a;
		if (a == 2)
		  return 0;
		return 1;
	  }
	}
	return 1;
}

int main (int argc, char *argv[]) {
	if (f (-2))
		abort ();
	exit (0);
}


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