[PATCH] Fix extract_range_from_cond (PR tree-optimization/19060)

Jakub Jelinek jakub@redhat.com
Fri Jan 7 09:26:00 GMT 2005


On Wed, Jan 05, 2005 at 11:49:45AM -0700, Jeffrey A Law wrote:
> We're probably best off doing two things:
> 
>   1. Fixing fold so that it handles x < TYPE_MIN_VALUE (TREE_TYPE (x))
>      (I thought it did that already, so we need to figure out why it
>       didn't trigger).
> 
>   2. For GT TYPE_MAX_VALUE, don't record anything.  Simliarly for
>      LT TYPE_MIN_VALUE.
> 
>   3. Document this code better (still in my TODO queue).

Here is what I have bootstrapped/regtested on
{i386,x86_64,ia64,ppc,ppc64,s390,s390x}-redhat-linux.
The problem with 1. is that fold only optimized this for
<= HOST_BITS_PER_WIDE_INT wide integer types, but that's easily fixable.
This exact patch has an gcc_unreachable there, so relies on fold optimizing
this out.  I have tried also:
+             /* The last element has not been processed.  Process it now.
+                record_range should ensure for cond inverted is not set.
+                This call can only fail if cond is x < min or x > max,
+                which fold should have optimized into false.
+                If that doesn't happen, just pretend all values are
+                in the range.  */
+             if (! extract_range_from_cond (element->cond, &tmp_high,
+                                            &tmp_low, &dummy))
+               {
+                 tree type = TREE_TYPE (TREE_OPERAND (element->cond, 1));
+                 tmp_low = TYPE_MIN_VALUE (type);
+                 tmp_high = TYPE_MAX_VALUE (type);
+               }
+             else
+               gcc_assert (dummy == 0);
+
which has a safety net just in the highly unprobable case fold doesn't
optimize such comparisons out, would that be preferable or do you think
it is best to test this in record_range and don't record that?

2005-01-07  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/19060
	* tree-ssa-dom.c (extract_range_from_cond) <case LT_EXPR, GT_EXPR>:
	Return 0 if op1 <= TYPE_MIN_VALUE () resp. op1 >= TYPE_MAX_VALUE ().
	(simplify_cond_and_lookup_avail_expr): Add assert for dummy == 0
	and handle extract_range_from_cond returning false.
	* fold-const.c (fold): Optimize comparisons with min/max even for
	width > HOST_BITS_PER_WIDE_INT.

	* gcc.c-torture/execute/20050104-1.c: New test.

--- gcc/fold-const.c.jj	2005-01-06 12:09:52.782028982 +0100
+++ gcc/fold-const.c	2005-01-06 12:41:24.559957382 +0100
@@ -8436,28 +8436,57 @@ fold (tree expr)
 
 	if (TREE_CODE (arg1) == INTEGER_CST
 	    && ! TREE_CONSTANT_OVERFLOW (arg1)
-	    && width <= HOST_BITS_PER_WIDE_INT
+	    && width <= 2 * HOST_BITS_PER_WIDE_INT
 	    && (INTEGRAL_TYPE_P (TREE_TYPE (arg1))
 		|| POINTER_TYPE_P (TREE_TYPE (arg1))))
 	  {
-	    unsigned HOST_WIDE_INT signed_max;
-	    unsigned HOST_WIDE_INT max, min;
+	    HOST_WIDE_INT signed_max_hi;
+	    unsigned HOST_WIDE_INT signed_max_lo;
+	    unsigned HOST_WIDE_INT max_hi, max_lo, min_hi, min_lo;
 
-	    signed_max = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
-
-	    if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+	    if (width <= HOST_BITS_PER_WIDE_INT)
 	      {
-	        max = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
-		min = 0;
+		signed_max_lo = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
+				- 1;
+		signed_max_hi = 0;
+		max_hi = 0;
+
+		if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+		  {
+		    max_lo = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+		    min_lo = 0;
+		    min_hi = 0;
+		  }
+		else
+		  {
+		    max_lo = signed_max_lo;
+		    min_lo = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+		    min_hi = -1;
+		  }
 	      }
 	    else
 	      {
-	        max = signed_max;
-		min = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+		width -= HOST_BITS_PER_WIDE_INT;
+		signed_max_lo = -1;
+		signed_max_hi = ((unsigned HOST_WIDE_INT) 1 << (width - 1))
+				- 1;
+		max_lo = -1;
+		min_lo = 0;
+
+		if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
+		  {
+		    max_hi = ((unsigned HOST_WIDE_INT) 2 << (width - 1)) - 1;
+		    min_hi = 0;
+		  }
+		else
+		  {
+		    max_hi = signed_max_hi;
+		    min_hi = ((unsigned HOST_WIDE_INT) -1 << (width - 1));
+		  }
 	      }
 
-	    if (TREE_INT_CST_HIGH (arg1) == 0
-		&& TREE_INT_CST_LOW (arg1) == max)
+	    if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1) == max_hi
+		&& TREE_INT_CST_LOW (arg1) == max_lo)
 	      switch (code)
 		{
 		case GT_EXPR:
@@ -8478,8 +8507,9 @@ fold (tree expr)
 		default:
 		  break;
 		}
-	    else if (TREE_INT_CST_HIGH (arg1) == 0
-		     && TREE_INT_CST_LOW (arg1) == max - 1)
+	    else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+		     == max_hi
+		     && TREE_INT_CST_LOW (arg1) == max_lo - 1)
 	      switch (code)
 		{
 		case GT_EXPR:
@@ -8491,8 +8521,9 @@ fold (tree expr)
 		default:
 		  break;
 		}
-	    else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
-		     && TREE_INT_CST_LOW (arg1) == min)
+	    else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+		     == min_hi
+		     && TREE_INT_CST_LOW (arg1) == min_lo)
 	      switch (code)
 		{
 		case LT_EXPR:
@@ -8510,8 +8541,9 @@ fold (tree expr)
 		default:
 		  break;
 		}
-	    else if (TREE_INT_CST_HIGH (arg1) == (min ? -1 : 0)
-		     && TREE_INT_CST_LOW (arg1) == min + 1)
+	    else if ((unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (arg1)
+		     == min_hi
+		     && TREE_INT_CST_LOW (arg1) == min_lo + 1)
 	      switch (code)
 		{
 		case GE_EXPR:
@@ -8525,8 +8557,8 @@ fold (tree expr)
 		}
 
 	    else if (!in_gimple_form
-		     && TREE_INT_CST_HIGH (arg1) == 0
-		     && TREE_INT_CST_LOW (arg1) == signed_max
+		     && TREE_INT_CST_HIGH (arg1) == signed_max_hi
+		     && TREE_INT_CST_LOW (arg1) == signed_max_lo
 		     && TYPE_UNSIGNED (TREE_TYPE (arg1))
 		     /* signed_type does not work on pointer types.  */
 		     && INTEGRAL_TYPE_P (TREE_TYPE (arg1)))
--- gcc/tree-ssa-dom.c.jj	2004-12-28 22:03:26.000000000 +0100
+++ gcc/tree-ssa-dom.c	2005-01-06 14:03:56.086431506 +0100
@@ -1,5 +1,5 @@
 /* SSA Dominator optimizations for trees
-   Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Diego Novillo <dnovillo@redhat.com>
 
 This file is part of GCC.
@@ -2088,10 +2088,18 @@ simplify_cond_and_lookup_avail_expr (tre
 	      tree tmp_high, tmp_low;
 	      int dummy;
 
-	      /* The last element has not been processed.  Process it now.  */
-	      extract_range_from_cond (element->cond, &tmp_high,
-				       &tmp_low, &dummy);
-	  
+	      /* The last element has not been processed.  Process it now.
+		 record_range should ensure for cond inverted is not set.
+		 This call can only fail if cond is x < min or x > max,
+		 which fold should have optimized into false.
+		 If that doesn't happen, just pretend all values are
+		 in the range.  */
+	      if (! extract_range_from_cond (element->cond, &tmp_high,
+					     &tmp_low, &dummy))
+		gcc_unreachable ();
+	      else
+		gcc_assert (dummy == 0);
+
 	      /* If this is the only element, then no merging is necessary, 
 		 the high/low values from extract_range_from_cond are all
 		 we need.  */
@@ -3204,8 +3212,10 @@ extract_range_from_cond (tree cond, tree
       break;
 
     case GT_EXPR:
-      low = int_const_binop (PLUS_EXPR, op1, integer_one_node, 1);
       high = TYPE_MAX_VALUE (type);
+      if (!tree_int_cst_lt (op1, high))
+	return 0;
+      low = int_const_binop (PLUS_EXPR, op1, integer_one_node, 1);
       inverted = 0;
       break;
 
@@ -3216,8 +3226,10 @@ extract_range_from_cond (tree cond, tree
       break;
 
     case LT_EXPR:
-      high = int_const_binop (MINUS_EXPR, op1, integer_one_node, 1);
       low = TYPE_MIN_VALUE (type);
+      if (tree_int_cst_equal (op1, low) || tree_int_cst_lt (op1, low))
+	return 0;
+      high = int_const_binop (MINUS_EXPR, op1, integer_one_node, 1);
       inverted = 0;
       break;
 
--- gcc/testsuite/gcc.c-torture/execute/20050104-1.c.jj	2005-01-04 17:58:38.000000000 +0100
+++ gcc/testsuite/gcc.c-torture/execute/20050104-1.c	2005-01-04 17:59:01.000000000 +0100
@@ -0,0 +1,23 @@
+/* PR tree-optimization/19060 */
+
+void abort (void);
+
+static
+long long min ()
+{
+  return -__LONG_LONG_MAX__ - 1;
+}
+
+void
+foo (long long j)
+{
+  if (j > 10 || j < min ())
+    abort ();
+}
+
+int
+main (void)
+{
+  foo (10);
+  return 0;
+}


	Jakub



More information about the Gcc-patches mailing list